Home | History | Annotate | Line # | Download | only in adb
adb_ms.c revision 1.18
      1  1.18  macallan /*	$NetBSD: adb_ms.c,v 1.18 2019/08/31 02:14:51 macallan Exp $	*/
      2   1.1  macallan 
      3   1.1  macallan /*
      4   1.1  macallan  * Copyright (C) 1998	Colin Wood
      5   1.5  macallan  * Copyright (C) 2006, 2007 Michael Lorenz
      6   1.1  macallan  * All rights reserved.
      7   1.1  macallan  *
      8   1.1  macallan  * Redistribution and use in source and binary forms, with or without
      9   1.1  macallan  * modification, are permitted provided that the following conditions
     10   1.1  macallan  * are met:
     11   1.1  macallan  * 1. Redistributions of source code must retain the above copyright
     12   1.1  macallan  *    notice, this list of conditions and the following disclaimer.
     13   1.1  macallan  * 2. Redistributions in binary form must reproduce the above copyright
     14   1.1  macallan  *    notice, this list of conditions and the following disclaimer in the
     15   1.1  macallan  *    documentation and/or other materials provided with the distribution.
     16   1.1  macallan  * 3. All advertising materials mentioning features or use of this software
     17   1.1  macallan  *    must display the following acknowledgement:
     18   1.1  macallan  *	This product includes software developed by Colin Wood.
     19   1.1  macallan  * 4. The name of the author may not be used to endorse or promote products
     20   1.1  macallan  *    derived from this software without specific prior written permission.
     21   1.1  macallan  *
     22   1.1  macallan  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23   1.1  macallan  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24   1.1  macallan  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25   1.1  macallan  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26   1.1  macallan  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     27   1.1  macallan  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28   1.1  macallan  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29   1.1  macallan  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30   1.1  macallan  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     31   1.1  macallan  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32   1.1  macallan  */
     33   1.1  macallan 
     34   1.1  macallan #include <sys/cdefs.h>
     35  1.18  macallan __KERNEL_RCSID(0, "$NetBSD: adb_ms.c,v 1.18 2019/08/31 02:14:51 macallan Exp $");
     36   1.1  macallan 
     37   1.1  macallan #include <sys/param.h>
     38   1.1  macallan #include <sys/device.h>
     39   1.1  macallan #include <sys/fcntl.h>
     40   1.1  macallan #include <sys/poll.h>
     41   1.1  macallan #include <sys/select.h>
     42   1.1  macallan #include <sys/proc.h>
     43   1.1  macallan #include <sys/signalvar.h>
     44   1.1  macallan #include <sys/systm.h>
     45   1.1  macallan #include <sys/kernel.h>
     46   1.4   tsutsui #include <sys/sysctl.h>
     47   1.1  macallan 
     48   1.1  macallan #include <machine/autoconf.h>
     49   1.1  macallan 
     50   1.1  macallan #include <dev/wscons/wsconsio.h>
     51   1.1  macallan #include <dev/wscons/wsmousevar.h>
     52   1.1  macallan 
     53   1.1  macallan #include <machine/adbsys.h>
     54   1.1  macallan #include <dev/adb/adbvar.h>
     55   1.1  macallan 
     56   1.1  macallan #include "adbdebug.h"
     57   1.1  macallan 
     58   1.1  macallan #ifdef ADBMS_DEBUG
     59   1.1  macallan #define DPRINTF printf
     60   1.1  macallan #else
     61   1.1  macallan #define DPRINTF while (0) printf
     62   1.1  macallan #endif
     63   1.1  macallan 
     64   1.1  macallan /*
     65   1.1  macallan  * State info, per mouse instance.
     66   1.1  macallan  */
     67   1.1  macallan struct adbms_softc {
     68   1.8      matt 	device_t	sc_dev;
     69   1.1  macallan 	struct adb_device *sc_adbdev;
     70   1.1  macallan 	struct adb_bus_accessops *sc_ops;
     71   1.1  macallan 
     72   1.1  macallan 	/* Extended Mouse Protocol info, faked for non-EMP mice */
     73   1.1  macallan 	u_int8_t	sc_class;	/* mouse class (mouse, trackball) */
     74   1.1  macallan 	u_int8_t	sc_buttons;	/* number of buttons */
     75   1.1  macallan 	u_int32_t	sc_res;		/* mouse resolution (dpi) */
     76   1.1  macallan 	char		sc_devid[5];	/* device indentifier */
     77   1.1  macallan 	uint8_t		sc_us;		/* cmd to watch for */
     78   1.1  macallan 	int		sc_mb;		/* current button state */
     79  1.14       chs 	device_t	sc_wsmousedev;
     80   1.1  macallan 	/* helpers for trackpads */
     81   1.1  macallan 	int		sc_down;
     82   1.1  macallan 	/*
     83   1.1  macallan 	 * trackpad protocol variant. Known so far:
     84   1.1  macallan 	 * 2 buttons - PowerBook 3400, single events on button 3 and 4 indicate
     85   1.1  macallan 	 *             finger down and up
     86   1.1  macallan 	 * 4 buttons - iBook G4, button 6 indicates finger down, button 4 is
     87   1.1  macallan 	 *             always down
     88   1.1  macallan 	 */
     89   1.1  macallan 	int		sc_x, sc_y;
     90   1.4   tsutsui 	int		sc_tapping;
     91   1.1  macallan 	/* buffers */
     92   1.1  macallan 	int		sc_poll;
     93   1.1  macallan 	int		sc_msg_len;
     94   1.1  macallan 	int		sc_event;
     95   1.1  macallan 	uint8_t		sc_buffer[16];
     96   1.1  macallan };
     97   1.1  macallan 
     98   1.1  macallan /* EMP device classes */
     99   1.1  macallan #define MSCLASS_TABLET		0
    100   1.1  macallan #define MSCLASS_MOUSE		1
    101   1.1  macallan #define MSCLASS_TRACKBALL	2
    102   1.1  macallan #define MSCLASS_TRACKPAD	3
    103   1.1  macallan 
    104   1.1  macallan /*
    105   1.1  macallan  * Function declarations.
    106   1.1  macallan  */
    107   1.8      matt static int	adbms_match(device_t, cfdata_t, void *);
    108   1.8      matt static void	adbms_attach(device_t, device_t, void *);
    109   1.1  macallan static void	ems_init(struct adbms_softc *);
    110   1.1  macallan static void	init_trackpad(struct adbms_softc *);
    111   1.1  macallan static void	adbms_init_mouse(struct adbms_softc *);
    112   1.1  macallan static void	adbms_init_turbo(struct adbms_softc *);
    113   1.1  macallan static void	adbms_init_uspeed(struct adbms_softc *);
    114   1.1  macallan static void	adbms_process_event(struct adbms_softc *, int, uint8_t *);
    115   1.1  macallan static int	adbms_send_sync(struct adbms_softc *, uint8_t, int, uint8_t *);
    116   1.1  macallan 
    117   1.1  macallan /* Driver definition. */
    118   1.8      matt CFATTACH_DECL_NEW(adbms, sizeof(struct adbms_softc),
    119   1.1  macallan     adbms_match, adbms_attach, NULL, NULL);
    120   1.1  macallan 
    121   1.1  macallan static int adbms_enable(void *);
    122   1.6  christos static int adbms_ioctl(void *, u_long, void *, int, struct lwp *);
    123   1.1  macallan static void adbms_disable(void *);
    124   1.1  macallan 
    125   1.1  macallan /*
    126   1.1  macallan  * handle tapping the trackpad
    127   1.1  macallan  * different pads report different button counts and use slightly different
    128   1.1  macallan  * protocols
    129   1.1  macallan  */
    130   1.1  macallan static void adbms_mangle_2(struct adbms_softc *, int);
    131   1.1  macallan static void adbms_mangle_4(struct adbms_softc *, int);
    132   1.1  macallan static void adbms_handler(void *, int, uint8_t *);
    133   1.1  macallan static int  adbms_wait(struct adbms_softc *, int);
    134   1.4   tsutsui static int  sysctl_adbms_tap(SYSCTLFN_ARGS);
    135   1.1  macallan 
    136   1.1  macallan const struct wsmouse_accessops adbms_accessops = {
    137   1.1  macallan 	adbms_enable,
    138   1.1  macallan 	adbms_ioctl,
    139   1.1  macallan 	adbms_disable,
    140   1.1  macallan };
    141   1.1  macallan 
    142   1.1  macallan static int
    143   1.8      matt adbms_match(device_t parent, cfdata_t cf, void *aux)
    144   1.1  macallan {
    145   1.1  macallan 	struct adb_attach_args *aaa = aux;
    146   1.1  macallan 
    147   1.1  macallan 	if (aaa->dev->original_addr == ADBADDR_MS)
    148   1.1  macallan 		return 1;
    149   1.1  macallan 	else
    150   1.1  macallan 		return 0;
    151   1.1  macallan }
    152   1.1  macallan 
    153   1.1  macallan static void
    154   1.8      matt adbms_attach(device_t parent, device_t self, void *aux)
    155   1.1  macallan {
    156   1.8      matt 	struct adbms_softc *sc = device_private(self);
    157   1.1  macallan 	struct adb_attach_args *aaa = aux;
    158   1.1  macallan 	struct wsmousedev_attach_args a;
    159   1.1  macallan 
    160   1.8      matt 	sc->sc_dev = self;
    161   1.1  macallan 	sc->sc_ops = aaa->ops;
    162   1.1  macallan 	sc->sc_adbdev = aaa->dev;
    163   1.1  macallan 	sc->sc_adbdev->cookie = sc;
    164   1.1  macallan 	sc->sc_adbdev->handler = adbms_handler;
    165   1.1  macallan 	sc->sc_us = ADBTALK(sc->sc_adbdev->current_addr, 0);
    166   1.7  macallan 	printf(" addr %d: ", sc->sc_adbdev->current_addr);
    167   1.1  macallan 
    168   1.1  macallan 	sc->sc_class = MSCLASS_MOUSE;
    169   1.1  macallan 	sc->sc_buttons = 1;
    170   1.1  macallan 	sc->sc_res = 100;
    171   1.1  macallan 	sc->sc_devid[0] = 0;
    172   1.1  macallan 	sc->sc_devid[4] = 0;
    173   1.1  macallan 	sc->sc_poll = 0;
    174   1.1  macallan 	sc->sc_msg_len = 0;
    175   1.4   tsutsui 	sc->sc_tapping = 1;
    176   1.1  macallan 
    177   1.1  macallan 	ems_init(sc);
    178   1.1  macallan 
    179   1.1  macallan 	/* print out the type of mouse we have */
    180   1.1  macallan 	switch (sc->sc_adbdev->handler_id) {
    181   1.1  macallan 	case ADBMS_100DPI:
    182  1.12  christos 		printf("%d-button, %u dpi mouse\n", sc->sc_buttons,
    183  1.12  christos 		    sc->sc_res);
    184   1.1  macallan 		break;
    185   1.1  macallan 	case ADBMS_200DPI:
    186   1.1  macallan 		sc->sc_res = 200;
    187  1.12  christos 		printf("%d-button, %u dpi mouse\n", sc->sc_buttons,
    188  1.12  christos 		    sc->sc_res);
    189   1.1  macallan 		break;
    190   1.1  macallan 	case ADBMS_MSA3:
    191  1.12  christos 		printf("Mouse Systems A3 mouse, %d-button, %u dpi\n",
    192  1.12  christos 		    sc->sc_buttons, sc->sc_res);
    193   1.1  macallan 		break;
    194   1.1  macallan 	case ADBMS_USPEED:
    195   1.1  macallan 		printf("MicroSpeed mouse, default parameters\n");
    196   1.1  macallan 		break;
    197   1.1  macallan 	case ADBMS_UCONTOUR:
    198   1.1  macallan 		printf("Contour mouse, default parameters\n");
    199   1.1  macallan 		break;
    200   1.1  macallan 	case ADBMS_TURBO:
    201   1.1  macallan 		printf("Kensington Turbo Mouse\n");
    202   1.1  macallan 		break;
    203   1.1  macallan 	case ADBMS_EXTENDED:
    204   1.1  macallan 		if (sc->sc_devid[0] == '\0') {
    205   1.1  macallan 			printf("Logitech ");
    206   1.1  macallan 			switch (sc->sc_class) {
    207   1.1  macallan 			case MSCLASS_MOUSE:
    208   1.1  macallan 				printf("MouseMan (non-EMP) mouse");
    209   1.1  macallan 				break;
    210   1.1  macallan 			case MSCLASS_TRACKBALL:
    211   1.1  macallan 				printf("TrackMan (non-EMP) trackball");
    212   1.1  macallan 				break;
    213   1.1  macallan 			default:
    214   1.1  macallan 				printf("non-EMP relative positioning device");
    215   1.1  macallan 				break;
    216   1.1  macallan 			}
    217   1.1  macallan 			printf("\n");
    218   1.1  macallan 		} else {
    219   1.1  macallan 			printf("EMP ");
    220   1.1  macallan 			switch (sc->sc_class) {
    221   1.1  macallan 			case MSCLASS_TABLET:
    222   1.1  macallan 				printf("tablet");
    223   1.1  macallan 				break;
    224   1.1  macallan 			case MSCLASS_MOUSE:
    225   1.1  macallan 				printf("mouse");
    226   1.1  macallan 				break;
    227   1.1  macallan 			case MSCLASS_TRACKBALL:
    228   1.1  macallan 				printf("trackball");
    229   1.1  macallan 				break;
    230   1.1  macallan 			case MSCLASS_TRACKPAD:
    231   1.1  macallan 				printf("trackpad");
    232   1.1  macallan 				init_trackpad(sc);
    233   1.1  macallan 				break;
    234   1.1  macallan 			default:
    235   1.1  macallan 				printf("unknown device");
    236   1.1  macallan 				break;
    237   1.1  macallan 			}
    238  1.12  christos 			printf(" <%s> %d-button, %u dpi\n", sc->sc_devid,
    239  1.12  christos 			    sc->sc_buttons, sc->sc_res);
    240   1.1  macallan 		}
    241   1.1  macallan 		break;
    242   1.1  macallan 	default:
    243   1.1  macallan 		printf("relative positioning device (mouse?) (%d)\n",
    244   1.1  macallan 			sc->sc_adbdev->handler_id);
    245   1.1  macallan 		break;
    246   1.1  macallan 	}
    247   1.1  macallan 
    248   1.1  macallan 	a.accessops = &adbms_accessops;
    249   1.1  macallan 	a.accesscookie = sc;
    250   1.1  macallan 	sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
    251   1.1  macallan }
    252   1.1  macallan 
    253   1.1  macallan 
    254   1.1  macallan /*
    255   1.1  macallan  * Initialize extended mouse support -- probes devices as described
    256   1.1  macallan  * in Inside Macintosh: Devices, Chapter 5 "ADB Manager".
    257   1.1  macallan  *
    258   1.1  macallan  * Extended Mouse Protocol is documented in TechNote HW1:
    259   1.1  macallan  * 	"ADB - The Untold Story:  Space Aliens Ate My Mouse"
    260   1.1  macallan  *
    261   1.1  macallan  * Supports: Extended Mouse Protocol, MicroSpeed Mouse Deluxe,
    262   1.1  macallan  * 	     Mouse Systems A^3 Mouse, Logitech non-EMP MouseMan
    263   1.1  macallan  */
    264   1.1  macallan void
    265   1.1  macallan ems_init(struct adbms_softc *sc)
    266   1.1  macallan {
    267   1.1  macallan 
    268   1.1  macallan 	DPRINTF("ems_init %d\n", sc->sc_adbdev->handler_id);
    269   1.1  macallan 
    270   1.1  macallan 	switch (sc->sc_adbdev->handler_id) {
    271   1.1  macallan 		case ADBMS_USPEED:
    272   1.1  macallan 		case ADBMS_UCONTOUR:
    273   1.1  macallan 			adbms_init_uspeed(sc);
    274   1.1  macallan 			return;
    275   1.1  macallan 		case ADBMS_TURBO:
    276   1.1  macallan 			adbms_init_turbo(sc);
    277   1.1  macallan 			return;
    278   1.1  macallan 		case ADBMS_100DPI:
    279   1.1  macallan 		case ADBMS_200DPI:
    280   1.1  macallan 			adbms_init_mouse(sc);
    281   1.1  macallan 	}
    282   1.1  macallan }
    283   1.1  macallan 
    284   1.1  macallan static void
    285   1.1  macallan adbms_init_uspeed(struct adbms_softc *sc)
    286   1.1  macallan {
    287   1.1  macallan 	uint8_t cmd, addr, buffer[4];
    288   1.1  macallan 
    289   1.1  macallan 	addr = sc->sc_adbdev->current_addr;
    290   1.1  macallan 
    291   1.1  macallan 	/* Found MicroSpeed Mouse Deluxe Mac or Contour Mouse */
    292   1.1  macallan 	cmd = ADBLISTEN(addr, 1);
    293   1.1  macallan 
    294   1.1  macallan 	/*
    295   1.1  macallan 	 * To setup the MicroSpeed or the Contour, it appears
    296   1.1  macallan 	 * that we can send the following command to the mouse
    297   1.1  macallan 	 * and then expect data back in the form:
    298   1.1  macallan 	 *  buffer[0] = 4 (bytes)
    299   1.1  macallan 	 *  buffer[1], buffer[2] as std. mouse
    300   1.1  macallan 	 *  buffer[3] = buffer[4] = 0xff when no buttons
    301   1.1  macallan 	 *   are down.  When button N down, bit N is clear.
    302   1.1  macallan 	 * buffer[4]'s locking mask enables a
    303   1.1  macallan 	 * click to toggle the button down state--sort of
    304   1.1  macallan 	 * like the "Easy Access" shift/control/etc. keys.
    305   1.1  macallan 	 * buffer[3]'s alternative speed mask enables using
    306   1.1  macallan 	 * different speed when the corr. button is down
    307   1.1  macallan 	 */
    308   1.1  macallan 	buffer[0] = 0x00;	/* Alternative speed */
    309   1.1  macallan 	buffer[1] = 0x00;	/* speed = maximum */
    310   1.1  macallan 	buffer[2] = 0x10;	/* enable extended protocol,
    311   1.1  macallan 				 * lower bits = alt. speed mask
    312   1.1  macallan 				 *            = 0000b
    313   1.1  macallan 				 */
    314   1.1  macallan 	buffer[3] = 0x07;	/* Locking mask = 0000b,
    315   1.1  macallan 				 * enable buttons = 0111b
    316   1.1  macallan 				 */
    317   1.1  macallan 	adbms_send_sync(sc, cmd, 4, buffer);
    318   1.1  macallan 
    319   1.1  macallan 	sc->sc_buttons = 3;
    320   1.1  macallan 	sc->sc_res = 200;
    321   1.1  macallan }
    322   1.1  macallan 
    323   1.1  macallan static void
    324   1.1  macallan adbms_init_turbo(struct adbms_softc *sc)
    325   1.1  macallan {
    326   1.1  macallan 	uint8_t addr;
    327   1.1  macallan 
    328   1.1  macallan 	/* Found Kensington Turbo Mouse */
    329  1.18  macallan 
    330  1.18  macallan /*
    331  1.18  macallan  * byte 1 assigns what which button does
    332  1.18  macallan  - 0x08 - button 1 - 1, button 2 - nothing
    333  1.18  macallan  - 0x09 - both buttons - 1
    334  1.18  macallan  - 0x0a - butoon 1 - 1, button 2 - toggle 1
    335  1.18  macallan  - 0x0b - button 1 - 1, button 2 - nothing
    336  1.18  macallan  - 0x0c - button 1 - 1, button 2 - 2
    337  1.18  macallan  - 0x0e - button 1 - 1, button 2 - 3
    338  1.18  macallan  - 0x0f - button 1 - 1, button 2 - toggle 3
    339  1.18  macallan  - 0x10 - button 1 toggle 1, button 2 nothing
    340  1.18  macallan  - 0x11 - button 1 - toggle 1, button 2 - 1
    341  1.18  macallan  - 0x12 - both toggle 1
    342  1.18  macallan  - 0x14 - button 1 toggle 1, button 2 - 2
    343  1.18  macallan  - 0x21 - button 1 - 2, button 2 - 1
    344  1.18  macallan  - 0x31 - button 1 - 3, button 2 - 1
    345  1.18  macallan  * byte 4 programs a delay for button presses, apparently in 1/100 seconds
    346  1.18  macallan  * byte 7 is some sort of checksum, writes will only stick if it's valid
    347  1.18  macallan           no idea how exactly it works yet, can't be too complicated considering
    348  1.18  macallan           the device's age
    349  1.18  macallan  */
    350  1.18  macallan 
    351  1.18  macallan /*
    352  1.18  macallan  * XXX
    353  1.18  macallan  * I doubt the first command is actually necessary. Leave in for now since it
    354  1.18  macallan  * doesn't do any harm either
    355  1.18  macallan  */
    356   1.1  macallan 	static u_char data1[] =
    357   1.1  macallan 		{ 0xe7, 0x8c, 0, 0, 0, 0xff, 0xff, 0x94 };
    358  1.18  macallan 
    359  1.18  macallan 	/* this seems to be the most reasonable default */
    360   1.1  macallan 	static u_char data2[] =
    361  1.18  macallan 		{ 0xa5, 0x0e, 0, 0, 1, 0xff, 0xff, 0x55 };
    362   1.1  macallan 
    363   1.1  macallan 	addr = sc->sc_adbdev->current_addr;
    364   1.1  macallan 
    365  1.18  macallan #ifdef ADBMS_DEBUG
    366  1.18  macallan 	{
    367  1.18  macallan 		int i;
    368  1.18  macallan 		adbms_send_sync(sc, ADBTALK(addr, 2), 0, NULL);
    369  1.18  macallan 		printf("reg *");
    370  1.18  macallan 		for (i = 0; i < sc->sc_msg_len; i++)
    371  1.18  macallan 			printf(" %02x", sc->sc_buffer[i]);
    372  1.18  macallan 		printf("\n");
    373  1.18  macallan 	}
    374  1.18  macallan #endif
    375  1.18  macallan 
    376   1.1  macallan 	adbms_send_sync(sc, ADBFLUSH(addr), 0, NULL);
    377   1.1  macallan 	adbms_send_sync(sc, ADBLISTEN(addr, 2), 8, data1);
    378   1.1  macallan 	adbms_send_sync(sc, ADBFLUSH(addr), 0, NULL);
    379   1.1  macallan 	adbms_send_sync(sc, ADBLISTEN(addr, 2), 8, data2);
    380  1.17  macallan 
    381  1.18  macallan #ifdef ADBMS_BRUTEFORCE
    382  1.18  macallan 	sc->sc_buffer[1] = 0;
    383  1.18  macallan 	int y = 0;
    384  1.18  macallan 	while ((sc->sc_buffer[1] != data2[1]) && (y < 0x100)) {
    385  1.18  macallan 		data2[7] = y;
    386  1.18  macallan 		y++;
    387  1.18  macallan 		adbms_send_sync(sc, ADBFLUSH(addr), 0, NULL);
    388  1.18  macallan 		adbms_send_sync(sc, ADBLISTEN(addr, 2), 8, data2);
    389  1.18  macallan 		adbms_send_sync(sc, ADBFLUSH(addr), 0, NULL);
    390  1.18  macallan 		adbms_send_sync(sc, ADBTALK(addr, 2), 0, NULL);
    391  1.18  macallan 	}
    392  1.18  macallan 	printf("y %02x\n", data2[7]);
    393  1.18  macallan #endif
    394  1.18  macallan 
    395  1.17  macallan #ifdef ADBMS_DEBUG
    396  1.17  macallan 	int i, reg;
    397  1.17  macallan 	for (reg = 1; reg < 4; reg++) {
    398  1.17  macallan 		adbms_send_sync(sc, ADBTALK(addr, reg), 0, NULL);
    399  1.17  macallan 		printf("reg %d", reg);
    400  1.17  macallan 		for (i = 0; i < sc->sc_msg_len; i++)
    401  1.17  macallan 			printf(" %02x", sc->sc_buffer[i]);
    402  1.17  macallan 		printf("\n");
    403  1.17  macallan 	}
    404  1.17  macallan #endif
    405   1.1  macallan }
    406   1.1  macallan 
    407   1.1  macallan static void
    408   1.1  macallan adbms_init_mouse(struct adbms_softc *sc)
    409   1.1  macallan {
    410   1.1  macallan 	int len;
    411   1.1  macallan 	uint8_t cmd, addr, buffer[16];
    412   1.1  macallan 
    413   1.1  macallan 	addr = sc->sc_adbdev->current_addr;
    414   1.1  macallan 	/* found a mouse */
    415   1.1  macallan 	cmd = ADBTALK(addr, 3);
    416   1.1  macallan 	if (!adbms_send_sync(sc, cmd, 0, NULL)) {
    417   1.1  macallan #ifdef ADBMS_DEBUG
    418   1.1  macallan 		printf("adb: ems_init timed out\n");
    419   1.1  macallan #endif
    420   1.1  macallan 		return;
    421   1.1  macallan 	}
    422   1.1  macallan 
    423   1.1  macallan 	/* Attempt to initialize Extended Mouse Protocol */
    424   1.1  macallan 	len = sc->sc_msg_len;
    425   1.1  macallan 	memcpy(buffer, sc->sc_buffer, len);
    426   1.1  macallan 	DPRINTF("buffer: %02x %02x\n", buffer[0], buffer[1]);
    427   1.1  macallan 	buffer[1] = 4; /* make handler ID 4 */
    428   1.1  macallan 	cmd = ADBLISTEN(addr, 3);
    429   1.1  macallan 	if (!adbms_send_sync(sc, cmd, len, buffer)) {
    430   1.1  macallan #ifdef ADBMS_DEBUG
    431   1.1  macallan 		printf("adb: ems_init timed out\n");
    432   1.1  macallan #endif
    433   1.1  macallan 		return;
    434   1.1  macallan 	}
    435   1.1  macallan 
    436   1.1  macallan 	/*
    437   1.1  macallan 	 * Check to see if successful, if not
    438   1.1  macallan 	 * try to initialize it as other types
    439   1.1  macallan 	 */
    440   1.1  macallan 	cmd = ADBTALK(addr, 3);
    441   1.1  macallan 	if (!adbms_send_sync(sc, cmd, 0, NULL)) {
    442   1.1  macallan 		DPRINTF("timeout checking for EMP switch\n");
    443   1.1  macallan 		return;
    444   1.1  macallan 	}
    445   1.1  macallan 	DPRINTF("new handler ID: %02x\n", sc->sc_buffer[1]);
    446   1.1  macallan 	if (sc->sc_buffer[1] == ADBMS_EXTENDED) {
    447   1.1  macallan 		sc->sc_adbdev->handler_id = ADBMS_EXTENDED;
    448   1.1  macallan 		cmd = ADBTALK(addr, 1);
    449   1.1  macallan 		if(!adbms_send_sync(sc, cmd, 0, NULL)) {
    450   1.1  macallan 			DPRINTF("adb: ems_init timed out\n");
    451   1.1  macallan 			return;
    452   1.1  macallan 		}
    453   1.1  macallan 
    454   1.1  macallan 		len = sc->sc_msg_len;
    455   1.1  macallan 		memcpy(buffer, sc->sc_buffer, len);
    456   1.1  macallan 
    457   1.1  macallan 		if (sc->sc_msg_len == 8) {
    458  1.12  christos 			uint16_t res;
    459   1.1  macallan 			/* we have a true EMP device */
    460   1.1  macallan #ifdef ADB_PRINT_EMP
    461   1.1  macallan 
    462   1.1  macallan 			printf("EMP: %02x %02x %02x %02x %02x %02x %02x %02x\n",
    463   1.1  macallan 			    buffer[0], buffer[1], buffer[2], buffer[3],
    464   1.1  macallan 			    buffer[4], buffer[5], buffer[6], buffer[7]);
    465   1.1  macallan #endif
    466  1.12  christos 			memcpy(sc->sc_devid, &buffer[0], 4);
    467  1.12  christos 			memcpy(&res, &buffer[4], sizeof(res));
    468  1.12  christos 			sc->sc_res = res;
    469   1.1  macallan 			sc->sc_class = buffer[6];
    470   1.1  macallan 			sc->sc_buttons = buffer[7];
    471   1.1  macallan 		} else if (buffer[0] == 0x9a &&
    472   1.1  macallan 		    ((buffer[1] == 0x20) || (buffer[1] == 0x21))) {
    473   1.1  macallan 			/*
    474   1.1  macallan 			 * Set up non-EMP Mouseman/Trackman to put
    475   1.1  macallan 			 * button bits in 3rd byte instead of sending
    476   1.1  macallan 			 * via pseudo keyboard device.
    477   1.1  macallan 			 */
    478   1.1  macallan 			if (buffer[1] == 0x21)
    479   1.1  macallan 				sc->sc_class = MSCLASS_TRACKBALL;
    480   1.1  macallan 			else
    481   1.1  macallan 				sc->sc_class = MSCLASS_MOUSE;
    482   1.1  macallan 
    483   1.1  macallan 			cmd = ADBLISTEN(addr, 1);
    484   1.1  macallan 			buffer[0]=0x00;
    485   1.1  macallan 			buffer[1]=0x81;
    486   1.1  macallan 			adbms_send_sync(sc, cmd, 2, buffer);
    487   1.1  macallan 
    488   1.1  macallan 			cmd = ADBLISTEN(addr, 1);
    489   1.1  macallan 			buffer[0]=0x01;
    490   1.1  macallan 			buffer[1]=0x81;
    491   1.1  macallan 			adbms_send_sync(sc, cmd, 2, buffer);
    492   1.1  macallan 
    493   1.1  macallan 			cmd = ADBLISTEN(addr, 1);
    494   1.1  macallan 			buffer[0]=0x02;
    495   1.1  macallan 			buffer[1]=0x81;
    496   1.1  macallan 			adbms_send_sync(sc, cmd, 2, buffer);
    497   1.1  macallan 
    498   1.1  macallan 			cmd = ADBLISTEN(addr, 1);
    499   1.1  macallan 			buffer[0]=0x03;
    500   1.1  macallan 			buffer[1]=0x38;
    501   1.1  macallan 			adbms_send_sync(sc, cmd, 2, buffer);
    502   1.1  macallan 
    503   1.1  macallan 			sc->sc_buttons = 3;
    504   1.1  macallan 			sc->sc_res = 400;
    505   1.1  macallan 		}
    506   1.1  macallan 	} else {
    507   1.1  macallan 		/* Attempt to initialize as an A3 mouse */
    508   1.1  macallan 		buffer[1] = 0x03; /* make handler ID 3 */
    509   1.1  macallan 		cmd = ADBLISTEN(addr, 3);
    510   1.1  macallan 		if (!adbms_send_sync(sc, cmd, len, buffer)) {
    511   1.1  macallan #ifdef ADBMS_DEBUG
    512   1.1  macallan 			printf("adb: ems_init timed out\n");
    513   1.1  macallan #endif
    514   1.1  macallan 			return;
    515   1.1  macallan 		}
    516   1.1  macallan 
    517   1.1  macallan 		/*
    518   1.1  macallan 		 * Check to see if successful, if not
    519   1.1  macallan 		 * try to initialize it as other types
    520   1.1  macallan 		 */
    521   1.1  macallan 		cmd = ADBTALK(addr, 3);
    522   1.1  macallan 		if(adbms_send_sync(sc, cmd, 0, NULL)) {
    523   1.1  macallan 			len = sc->sc_msg_len;
    524   1.1  macallan 			memcpy(buffer, sc->sc_buffer, len);
    525   1.1  macallan 			if (buffer[1] == ADBMS_MSA3) {
    526   1.1  macallan 				sc->sc_adbdev->handler_id = ADBMS_MSA3;
    527   1.1  macallan 				/* Initialize as above */
    528   1.1  macallan 				cmd = ADBLISTEN(addr, 2);
    529   1.1  macallan 				/* listen 2 */
    530   1.1  macallan 				buffer[0] = 0x00;
    531   1.1  macallan 				/* Irrelevant, buffer has 0x77 */
    532   1.1  macallan 				buffer[2] = 0x07;
    533   1.1  macallan 				/*
    534   1.1  macallan 				 * enable 3 button mode = 0111b,
    535   1.1  macallan 				 * speed = normal
    536   1.1  macallan 				 */
    537   1.1  macallan 				adbms_send_sync(sc, cmd, 3, buffer);
    538   1.1  macallan 				sc->sc_buttons = 3;
    539   1.1  macallan 				sc->sc_res = 300;
    540   1.1  macallan 			}
    541   1.1  macallan 		}
    542   1.1  macallan 	}
    543   1.1  macallan }
    544   1.1  macallan 
    545   1.1  macallan static void
    546   1.1  macallan adbms_handler(void *cookie, int len, uint8_t *data)
    547   1.1  macallan {
    548   1.1  macallan 	struct adbms_softc *sc = cookie;
    549   1.1  macallan 
    550   1.1  macallan #ifdef ADBMS_DEBUG
    551   1.1  macallan 	int i;
    552   1.8      matt 	printf("%s: %02x - ", device_xname(sc->sc_dev), sc->sc_us);
    553   1.1  macallan 	for (i = 0; i < len; i++) {
    554   1.1  macallan 		printf(" %02x", data[i]);
    555   1.1  macallan 	}
    556   1.1  macallan 	printf("\n");
    557   1.1  macallan #endif
    558   1.1  macallan 	if (len >= 2) {
    559   1.1  macallan 		memcpy(sc->sc_buffer, &data[2], len - 2);
    560   1.1  macallan 		sc->sc_msg_len = len - 2;
    561   1.1  macallan 		if (data[1] == sc->sc_us) {
    562   1.1  macallan 			/* make sense of the mouse message */
    563   1.1  macallan 			adbms_process_event(sc, sc->sc_msg_len, sc->sc_buffer);
    564   1.1  macallan 			return;
    565   1.1  macallan 		}
    566   1.1  macallan 		wakeup(&sc->sc_event);
    567   1.1  macallan 	} else {
    568   1.1  macallan 		DPRINTF("bogus message\n");
    569   1.1  macallan 	}
    570   1.1  macallan }
    571   1.1  macallan 
    572   1.1  macallan static void
    573   1.1  macallan adbms_process_event(struct adbms_softc *sc, int len, uint8_t *buffer)
    574   1.1  macallan {
    575   1.1  macallan 	int buttons = 0, mask, dx, dy, i;
    576   1.1  macallan 	int button_bit = 1;
    577   1.1  macallan 
    578   1.1  macallan 	if ((sc->sc_adbdev->handler_id == ADBMS_EXTENDED) && (sc->sc_devid[0] == 0)) {
    579   1.1  macallan 		/* massage the data to look like EMP data */
    580   1.1  macallan 		if ((buffer[2] & 0x04) == 0x04)
    581   1.1  macallan 			buffer[0] &= 0x7f;
    582   1.1  macallan 		else
    583   1.1  macallan 			buffer[0] |= 0x80;
    584   1.1  macallan 		if ((buffer[2] & 0x02) == 0x02)
    585   1.1  macallan 			buffer[1] &= 0x7f;
    586   1.1  macallan 		else
    587   1.1  macallan 			buffer[1] |= 0x80;
    588   1.1  macallan 		if ((buffer[2] & 0x01) == 0x01)
    589   1.1  macallan 			buffer[2] = 0x00;
    590   1.1  macallan 		else
    591   1.1  macallan 			buffer[2] = 0x80;
    592   1.1  macallan 	}
    593   1.1  macallan 
    594   1.1  macallan 	switch (sc->sc_adbdev->handler_id) {
    595   1.1  macallan 		case ADBMS_USPEED:
    596   1.1  macallan 		case ADBMS_UCONTOUR:
    597   1.1  macallan 			/* MicroSpeed mouse and Contour mouse */
    598   1.1  macallan 			if (len == 4)
    599   1.1  macallan 				buttons = (~buffer[3]) & 0xff;
    600   1.1  macallan 			else
    601   1.1  macallan 				buttons = (buffer[1] & 0x80) ? 0 : 1;
    602   1.1  macallan 			break;
    603   1.1  macallan 		case ADBMS_MSA3:
    604   1.1  macallan 			/* Mouse Systems A3 mouse */
    605   1.1  macallan 			if (len == 3)
    606   1.1  macallan 				buttons = (~buffer[2]) & 0x07;
    607   1.1  macallan 			else
    608   1.1  macallan 				buttons = (buffer[0] & 0x80) ? 0 : 1;
    609   1.1  macallan 			break;
    610   1.1  macallan 		default:
    611   1.1  macallan 			/* Classic Mouse Protocol (up to 2 buttons) */
    612   1.1  macallan 			for (i = 0; i < 2; i++, button_bit <<= 1)
    613   1.1  macallan 				/* 0 when button down */
    614   1.1  macallan 				if (!(buffer[i] & 0x80))
    615   1.1  macallan 					buttons |= button_bit;
    616   1.1  macallan 				else
    617   1.1  macallan 					buttons &= ~button_bit;
    618   1.1  macallan 			/* Extended Protocol (up to 6 more buttons) */
    619   1.1  macallan 			for (mask = 0x80; i < len;
    620   1.1  macallan 			     i += (mask == 0x80), button_bit <<= 1) {
    621   1.1  macallan 				/* 0 when button down */
    622   1.1  macallan 				if (!(buffer[i] & mask))
    623   1.1  macallan 					buttons |= button_bit;
    624   1.1  macallan 				else
    625   1.1  macallan 					buttons &= ~button_bit;
    626   1.1  macallan 				mask = ((mask >> 4) & 0xf)
    627   1.1  macallan 					| ((mask & 0xf) << 4);
    628   1.1  macallan 			}
    629   1.1  macallan 			break;
    630   1.1  macallan 	}
    631   1.1  macallan 
    632  1.17  macallan 	if ((sc->sc_adbdev->handler_id != ADBMS_EXTENDED) &&
    633  1.17  macallan 	    (sc->sc_adbdev->handler_id != ADBMS_TURBO)) {
    634  1.16  macallan 		dx = ((int)(buffer[1] & 0x3f)) - ((buffer[1] & 0x40) ? 64 : 0);
    635  1.16  macallan 		dy = ((int)(buffer[0] & 0x3f)) - ((buffer[0] & 0x40) ? 64 : 0);
    636  1.16  macallan 	} else {
    637  1.16  macallan 		/* EMP crap, additional motion bits */
    638  1.16  macallan 		int shift = 7, ddx, ddy, sign, smask;
    639  1.16  macallan 
    640  1.16  macallan #ifdef ADBMS_DEBUG
    641  1.16  macallan 		printf("EMP packet:");
    642  1.16  macallan 		for (i = 0; i < len; i++)
    643  1.16  macallan 			printf(" %02x", buffer[i]);
    644  1.16  macallan 		printf("\n");
    645  1.16  macallan #endif
    646  1.16  macallan 		dx = (int)buffer[1] & 0x7f;
    647  1.16  macallan 		dy = (int)buffer[0] & 0x7f;
    648  1.16  macallan 		for (i = 2; i < len; i++) {
    649  1.16  macallan 			ddx = (buffer[i] & 0x07);
    650  1.16  macallan 			ddy = (buffer[i] & 0x70) >> 4;
    651  1.16  macallan 			dx |= (ddx << shift);
    652  1.16  macallan 			dy |= (ddy << shift);
    653  1.16  macallan 			shift += 3;
    654  1.16  macallan 		}
    655  1.16  macallan 		sign = 1 << (shift - 1);
    656  1.16  macallan 		smask = 0xffffffff << shift;
    657  1.16  macallan 		if (dx & sign)
    658  1.16  macallan 			dx |= smask;
    659  1.16  macallan 		if (dy & sign)
    660  1.16  macallan 			dy |= smask;
    661  1.16  macallan #ifdef ADBMS_DEBUG
    662  1.16  macallan 		printf("%d %d %08x %d\n", dx, dy, smask, shift);
    663  1.16  macallan #endif
    664  1.16  macallan 	}
    665   1.1  macallan 
    666   1.1  macallan 	if (sc->sc_class == MSCLASS_TRACKPAD) {
    667   1.1  macallan 
    668   1.4   tsutsui 		if (sc->sc_tapping == 1) {
    669   1.4   tsutsui 			if (sc->sc_down) {
    670   1.4   tsutsui 				/* finger is down - collect motion data */
    671   1.4   tsutsui 				sc->sc_x += dx;
    672   1.4   tsutsui 				sc->sc_y += dy;
    673   1.4   tsutsui 			}
    674   1.4   tsutsui 			DPRINTF("buttons: %02x\n", buttons);
    675   1.4   tsutsui 			switch (sc->sc_buttons) {
    676   1.4   tsutsui 				case 2:
    677   1.4   tsutsui 					buttons |= ((buttons & 2) >> 1);
    678   1.4   tsutsui 					adbms_mangle_2(sc, buttons);
    679   1.4   tsutsui 					break;
    680   1.4   tsutsui 				case 4:
    681   1.4   tsutsui 					adbms_mangle_4(sc, buttons);
    682   1.4   tsutsui 					break;
    683   1.4   tsutsui 			}
    684   1.1  macallan 		}
    685   1.1  macallan 		/* filter the pseudo-buttons out */
    686   1.1  macallan 		buttons &= 1;
    687   1.1  macallan 	}
    688   1.1  macallan 
    689   1.1  macallan 	if (sc->sc_wsmousedev)
    690   1.1  macallan 		wsmouse_input(sc->sc_wsmousedev, sc->sc_mb | buttons,
    691   1.1  macallan 			      dx, -dy, 0, 0,
    692   1.1  macallan 			      WSMOUSE_INPUT_DELTA);
    693   1.1  macallan #if NAED > 0
    694   1.1  macallan 	aed_input(&new_event);
    695   1.1  macallan #endif
    696   1.1  macallan }
    697   1.1  macallan 
    698   1.1  macallan static void
    699   1.1  macallan adbms_mangle_2(struct adbms_softc *sc, int buttons)
    700   1.1  macallan {
    701   1.1  macallan 
    702   1.1  macallan 	if (buttons & 4) {
    703   1.1  macallan 		/* finger down on pad */
    704   1.1  macallan 		if (sc->sc_down == 0) {
    705   1.1  macallan 			sc->sc_down = 1;
    706   1.1  macallan 			sc->sc_x = 0;
    707   1.1  macallan 			sc->sc_y = 0;
    708   1.1  macallan 		}
    709   1.1  macallan 	}
    710   1.1  macallan 	if (buttons & 8) {
    711   1.1  macallan 		/* finger up */
    712   1.1  macallan 		if (sc->sc_down) {
    713   1.1  macallan 			if (((sc->sc_x * sc->sc_x +
    714   1.9  macallan 			    sc->sc_y * sc->sc_y) < 3) &&
    715   1.1  macallan 			    (sc->sc_wsmousedev)) {
    716   1.1  macallan 				/*
    717   1.1  macallan 				 * if there wasn't much movement between
    718   1.1  macallan 				 * finger down and up again we assume
    719   1.1  macallan 				 * someone tapped the pad and we just
    720   1.1  macallan 				 * send a mouse button event
    721   1.1  macallan 				 */
    722   1.1  macallan 				wsmouse_input(sc->sc_wsmousedev,
    723   1.1  macallan 				    1, 0, 0, 0, 0, WSMOUSE_INPUT_DELTA);
    724   1.1  macallan 			}
    725   1.1  macallan 			sc->sc_down = 0;
    726   1.1  macallan 		}
    727   1.1  macallan 	}
    728   1.1  macallan }
    729   1.1  macallan 
    730   1.1  macallan static void
    731   1.1  macallan adbms_mangle_4(struct adbms_softc *sc, int buttons)
    732   1.1  macallan {
    733   1.1  macallan 
    734   1.1  macallan 	if (buttons & 0x20) {
    735   1.1  macallan 		/* finger down on pad */
    736   1.1  macallan 		if (sc->sc_down == 0) {
    737   1.1  macallan 			sc->sc_down = 1;
    738   1.1  macallan 			sc->sc_x = 0;
    739   1.1  macallan 			sc->sc_y = 0;
    740   1.1  macallan 		}
    741   1.1  macallan 	}
    742   1.1  macallan 	if ((buttons & 0x20) == 0) {
    743   1.1  macallan 		/* finger up */
    744   1.1  macallan 		if (sc->sc_down) {
    745   1.1  macallan 			if (((sc->sc_x * sc->sc_x +
    746   1.9  macallan 			    sc->sc_y * sc->sc_y) < 3) &&
    747   1.1  macallan 			    (sc->sc_wsmousedev)) {
    748   1.1  macallan 				/*
    749   1.1  macallan 				 * if there wasn't much movement between
    750   1.1  macallan 				 * finger down and up again we assume
    751   1.1  macallan 				 * someone tapped the pad and we just
    752   1.1  macallan 				 * send a mouse button event
    753   1.1  macallan 				 */
    754   1.1  macallan 				wsmouse_input(sc->sc_wsmousedev,
    755   1.1  macallan 				    1, 0, 0, 0, 0, WSMOUSE_INPUT_DELTA);
    756   1.1  macallan 			}
    757   1.1  macallan 			sc->sc_down = 0;
    758   1.1  macallan 		}
    759   1.1  macallan 	}
    760   1.1  macallan }
    761   1.1  macallan 
    762   1.1  macallan static int
    763   1.1  macallan adbms_enable(void *v)
    764   1.1  macallan {
    765   1.1  macallan 	return 0;
    766   1.1  macallan }
    767   1.1  macallan 
    768   1.1  macallan static int
    769   1.6  christos adbms_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
    770   1.1  macallan {
    771   1.1  macallan 
    772   1.1  macallan 	switch (cmd) {
    773   1.1  macallan 	case WSMOUSEIO_GTYPE:
    774   1.1  macallan 		*(u_int *)data = WSMOUSE_TYPE_ADB;
    775   1.1  macallan 		break;
    776   1.1  macallan 
    777   1.1  macallan 	default:
    778   1.1  macallan 		return (EPASSTHROUGH);
    779   1.1  macallan 	}
    780   1.1  macallan 	return (0);
    781   1.1  macallan }
    782   1.1  macallan 
    783   1.1  macallan static void
    784   1.1  macallan adbms_disable(void *v)
    785   1.1  macallan {
    786   1.1  macallan }
    787   1.1  macallan 
    788   1.1  macallan static void
    789   1.1  macallan init_trackpad(struct adbms_softc *sc)
    790   1.1  macallan {
    791  1.10  macallan 	const struct sysctlnode *me = NULL, *node = NULL;
    792   1.4   tsutsui 	int cmd, addr, ret;
    793   1.1  macallan 	uint8_t buffer[16];
    794   1.1  macallan 	uint8_t b2[] = {0x99, 0x94, 0x19, 0xff, 0xb2, 0x8a, 0x1b, 0x50};
    795   1.1  macallan 
    796   1.1  macallan 	addr = sc->sc_adbdev->current_addr;
    797   1.1  macallan 	cmd = ADBTALK(addr, 1);
    798   1.1  macallan 	if (!adbms_send_sync(sc, cmd, 0, NULL))
    799   1.1  macallan 		return;
    800   1.1  macallan 
    801   1.1  macallan 	if (sc->sc_msg_len != 8)
    802   1.1  macallan 		return;
    803   1.1  macallan 
    804   1.1  macallan 	memcpy(buffer, sc->sc_buffer, 8);
    805   1.1  macallan 
    806   1.1  macallan 	/* now whack the pad */
    807   1.1  macallan 	cmd = ADBLISTEN(addr, 1);
    808   1.1  macallan 	buffer[6] = 0x0d;
    809   1.1  macallan 	adbms_send_sync(sc, cmd, 8, buffer);
    810   1.1  macallan 
    811   1.1  macallan 	delay(1000);
    812   1.1  macallan 	cmd = ADBLISTEN(addr, 2);
    813   1.1  macallan 	adbms_send_sync(sc, cmd, 8, b2);
    814   1.1  macallan 
    815   1.1  macallan 	delay(1000);
    816   1.1  macallan 	cmd = ADBLISTEN(addr, 1);
    817   1.1  macallan 	buffer[6] = 0x03;
    818   1.1  macallan 	adbms_send_sync(sc, cmd, 8, buffer);
    819   1.1  macallan 
    820   1.1  macallan 	cmd = ADBFLUSH(addr);
    821   1.1  macallan 	adbms_send_sync(sc, cmd, 0, NULL);
    822   1.1  macallan 	delay(1000);
    823   1.4   tsutsui 
    824   1.4   tsutsui 	/*
    825  1.11   mbalmer 	 * setup a sysctl node to control whether tapping the pad should
    826   1.4   tsutsui 	 * trigger mouse button events
    827   1.4   tsutsui 	 */
    828   1.4   tsutsui 
    829   1.4   tsutsui 	sc->sc_tapping = 1;
    830   1.4   tsutsui 
    831  1.10  macallan 	ret = sysctl_createv(NULL, 0, NULL, &me,
    832   1.4   tsutsui 	    CTLFLAG_READWRITE,
    833   1.8      matt 	    CTLTYPE_NODE, device_xname(sc->sc_dev), NULL,
    834   1.4   tsutsui 	    NULL, 0, NULL, 0,
    835   1.4   tsutsui 	    CTL_MACHDEP, CTL_CREATE, CTL_EOL);
    836   1.4   tsutsui 
    837  1.10  macallan 	ret = sysctl_createv(NULL, 0, NULL, &node,
    838  1.10  macallan 	    CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
    839   1.4   tsutsui 	    CTLTYPE_INT, "tapping", "tapping the pad causes button events",
    840  1.13       dsl 	    sysctl_adbms_tap, 1, (void *)sc, 0,
    841   1.4   tsutsui 	    CTL_MACHDEP, me->sysctl_num, CTL_CREATE, CTL_EOL);
    842  1.15  nisimura 
    843  1.15  nisimura 	(void)ret;
    844   1.1  macallan }
    845   1.1  macallan 
    846   1.1  macallan static int
    847   1.1  macallan adbms_wait(struct adbms_softc *sc, int timeout)
    848   1.1  macallan {
    849   1.1  macallan 	int cnt = 0;
    850   1.1  macallan 
    851   1.1  macallan 	if (sc->sc_poll) {
    852   1.1  macallan 		while (sc->sc_msg_len == -1) {
    853   1.1  macallan 			sc->sc_ops->poll(sc->sc_ops->cookie);
    854   1.1  macallan 		}
    855   1.1  macallan 	} else {
    856   1.1  macallan 		while ((sc->sc_msg_len == -1) && (cnt < timeout)) {
    857   1.9  macallan 			tsleep(&sc->sc_event, 0, "adbmsio", hz);
    858   1.1  macallan 			cnt++;
    859   1.1  macallan 		}
    860   1.1  macallan 	}
    861   1.1  macallan 	return (sc->sc_msg_len > 0);
    862   1.1  macallan }
    863   1.1  macallan 
    864   1.1  macallan static int
    865   1.1  macallan adbms_send_sync(struct adbms_softc *sc, uint8_t cmd, int len, uint8_t *msg)
    866   1.1  macallan {
    867   1.1  macallan 	int i;
    868   1.1  macallan 
    869   1.1  macallan 	sc->sc_msg_len = -1;
    870   1.1  macallan 	DPRINTF("send: %02x", cmd);
    871   1.1  macallan 	for (i = 0; i < len; i++)
    872   1.1  macallan 		DPRINTF(" %02x", msg[i]);
    873   1.1  macallan 	DPRINTF("\n");
    874   1.1  macallan 	sc->sc_ops->send(sc->sc_ops->cookie, sc->sc_poll, cmd, len, msg);
    875  1.17  macallan 	adbms_wait(sc, 3);
    876   1.1  macallan 	return (sc->sc_msg_len != -1);
    877   1.1  macallan }
    878   1.4   tsutsui 
    879   1.4   tsutsui static int
    880   1.4   tsutsui sysctl_adbms_tap(SYSCTLFN_ARGS)
    881   1.4   tsutsui {
    882   1.4   tsutsui 	struct sysctlnode node = *rnode;
    883   1.4   tsutsui 	struct adbms_softc *sc = node.sysctl_data;
    884   1.4   tsutsui 
    885   1.4   tsutsui 	node.sysctl_idata = sc->sc_tapping;
    886   1.4   tsutsui 
    887   1.4   tsutsui 	if (newp) {
    888   1.4   tsutsui 
    889   1.4   tsutsui 		/* we're asked to write */
    890   1.4   tsutsui 		node.sysctl_data = &sc->sc_tapping;
    891   1.4   tsutsui 		if (sysctl_lookup(SYSCTLFN_CALL(&node)) == 0) {
    892   1.4   tsutsui 
    893  1.10  macallan 			sc->sc_tapping = (*(int *)node.sysctl_data == 0) ? 0 : 1;
    894   1.4   tsutsui 			return 0;
    895   1.4   tsutsui 		}
    896   1.4   tsutsui 		return EINVAL;
    897   1.4   tsutsui 	} else {
    898   1.4   tsutsui 
    899  1.10  macallan 		node.sysctl_data = &sc->sc_tapping;
    900   1.4   tsutsui 		node.sysctl_size = 4;
    901   1.4   tsutsui 		return (sysctl_lookup(SYSCTLFN_CALL(&node)));
    902   1.4   tsutsui 	}
    903   1.4   tsutsui 
    904   1.4   tsutsui 	return 0;
    905   1.4   tsutsui }
    906   1.4   tsutsui 
    907   1.4   tsutsui SYSCTL_SETUP(sysctl_ams_setup, "sysctl ams subtree setup")
    908   1.4   tsutsui {
    909   1.4   tsutsui 
    910   1.4   tsutsui 	sysctl_createv(NULL, 0, NULL, NULL,
    911   1.4   tsutsui 		       CTLFLAG_PERMANENT,
    912   1.4   tsutsui 		       CTLTYPE_NODE, "machdep", NULL,
    913   1.4   tsutsui 		       NULL, 0, NULL, 0,
    914   1.4   tsutsui 		       CTL_MACHDEP, CTL_EOL);
    915   1.4   tsutsui }
    916