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