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