adb_ktm.c revision 1.1 1 1.1 macallan /* $NetBSD: adb_ktm.c,v 1.1 2019/09/08 05:55:15 macallan Exp $ */
2 1.1 macallan
3 1.1 macallan /*-
4 1.1 macallan * Copyright (c) 2019 Michael Lorenz
5 1.1 macallan * All rights reserved.
6 1.1 macallan *
7 1.1 macallan * Redistribution and use in source and binary forms, with or without
8 1.1 macallan * modification, are permitted provided that the following conditions
9 1.1 macallan * are met:
10 1.1 macallan * 1. Redistributions of source code must retain the above copyright
11 1.1 macallan * notice, this list of conditions and the following disclaimer.
12 1.1 macallan * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 macallan * notice, this list of conditions and the following disclaimer in the
14 1.1 macallan * documentation and/or other materials provided with the distribution.
15 1.1 macallan *
16 1.1 macallan * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 1.1 macallan * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 1.1 macallan * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 1.1 macallan * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 1.1 macallan * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 1.1 macallan * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 1.1 macallan * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 1.1 macallan * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 1.1 macallan * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 1.1 macallan * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 1.1 macallan * POSSIBILITY OF SUCH DAMAGE.
27 1.1 macallan */
28 1.1 macallan
29 1.1 macallan #include <sys/cdefs.h>
30 1.1 macallan __KERNEL_RCSID(0, "$NetBSD: adb_ktm.c,v 1.1 2019/09/08 05:55:15 macallan Exp $");
31 1.1 macallan
32 1.1 macallan #include <sys/param.h>
33 1.1 macallan #include <sys/device.h>
34 1.1 macallan #include <sys/fcntl.h>
35 1.1 macallan #include <sys/systm.h>
36 1.1 macallan #include <sys/kernel.h>
37 1.1 macallan #include <sys/sysctl.h>
38 1.1 macallan
39 1.1 macallan #include <machine/autoconf.h>
40 1.1 macallan
41 1.1 macallan #include <dev/wscons/wsconsio.h>
42 1.1 macallan #include <dev/wscons/wsmousevar.h>
43 1.1 macallan
44 1.1 macallan #include <machine/adbsys.h>
45 1.1 macallan #include <dev/adb/adbvar.h>
46 1.1 macallan
47 1.1 macallan #include "adbdebug.h"
48 1.1 macallan
49 1.1 macallan #ifdef KTM_DEBUG
50 1.1 macallan #define DPRINTF printf
51 1.1 macallan #else
52 1.1 macallan #define DPRINTF while (0) printf
53 1.1 macallan #endif
54 1.1 macallan
55 1.1 macallan /*
56 1.1 macallan * State info, per mouse instance.
57 1.1 macallan */
58 1.1 macallan struct ktm_softc {
59 1.1 macallan device_t sc_dev;
60 1.1 macallan struct adb_device *sc_adbdev;
61 1.1 macallan struct adb_bus_accessops *sc_ops;
62 1.1 macallan
63 1.1 macallan uint8_t sc_us; /* cmd to watch for */
64 1.1 macallan device_t sc_wsmousedev;
65 1.1 macallan /* buffers */
66 1.1 macallan uint8_t sc_config[8];
67 1.1 macallan int sc_left;
68 1.1 macallan int sc_right;
69 1.1 macallan int sc_poll;
70 1.1 macallan int sc_msg_len;
71 1.1 macallan int sc_event;
72 1.1 macallan uint8_t sc_buffer[16];
73 1.1 macallan };
74 1.1 macallan
75 1.1 macallan /*
76 1.1 macallan * Function declarations.
77 1.1 macallan */
78 1.1 macallan static int ktm_match(device_t, cfdata_t, void *);
79 1.1 macallan static void ktm_attach(device_t, device_t, void *);
80 1.1 macallan static void ktm_init(struct ktm_softc *);
81 1.1 macallan static void ktm_write_config(struct ktm_softc *);
82 1.1 macallan static void ktm_buttons(struct ktm_softc *);
83 1.1 macallan static void ktm_process_event(struct ktm_softc *, int, uint8_t *);
84 1.1 macallan static int ktm_send_sync(struct ktm_softc *, uint8_t, int, uint8_t *);
85 1.1 macallan
86 1.1 macallan /* Driver definition. */
87 1.1 macallan CFATTACH_DECL_NEW(ktm, sizeof(struct ktm_softc),
88 1.1 macallan ktm_match, ktm_attach, NULL, NULL);
89 1.1 macallan
90 1.1 macallan static int ktm_enable(void *);
91 1.1 macallan static int ktm_ioctl(void *, u_long, void *, int, struct lwp *);
92 1.1 macallan static void ktm_disable(void *);
93 1.1 macallan
94 1.1 macallan static void ktm_handler(void *, int, uint8_t *);
95 1.1 macallan static int ktm_wait(struct ktm_softc *, int);
96 1.1 macallan static int sysctl_ktm_left(SYSCTLFN_ARGS);
97 1.1 macallan static int sysctl_ktm_right(SYSCTLFN_ARGS);
98 1.1 macallan
99 1.1 macallan const struct wsmouse_accessops ktm_accessops = {
100 1.1 macallan ktm_enable,
101 1.1 macallan ktm_ioctl,
102 1.1 macallan ktm_disable,
103 1.1 macallan };
104 1.1 macallan
105 1.1 macallan static int
106 1.1 macallan ktm_match(device_t parent, cfdata_t cf, void *aux)
107 1.1 macallan {
108 1.1 macallan struct adb_attach_args *aaa = aux;
109 1.1 macallan if ((aaa->dev->original_addr == ADBADDR_MS) &&
110 1.1 macallan (aaa->dev->handler_id == ADBMS_TURBO))
111 1.1 macallan return 50; /* beat out adbms */
112 1.1 macallan else
113 1.1 macallan return 0;
114 1.1 macallan }
115 1.1 macallan
116 1.1 macallan static void
117 1.1 macallan ktm_attach(device_t parent, device_t self, void *aux)
118 1.1 macallan {
119 1.1 macallan struct ktm_softc *sc = device_private(self);
120 1.1 macallan struct adb_attach_args *aaa = aux;
121 1.1 macallan struct wsmousedev_attach_args a;
122 1.1 macallan
123 1.1 macallan sc->sc_dev = self;
124 1.1 macallan sc->sc_ops = aaa->ops;
125 1.1 macallan sc->sc_adbdev = aaa->dev;
126 1.1 macallan sc->sc_adbdev->cookie = sc;
127 1.1 macallan sc->sc_adbdev->handler = ktm_handler;
128 1.1 macallan sc->sc_us = ADBTALK(sc->sc_adbdev->current_addr, 0);
129 1.1 macallan printf(" addr %d: Kensington Turbo Mouse\n",
130 1.1 macallan sc->sc_adbdev->current_addr);
131 1.1 macallan
132 1.1 macallan sc->sc_poll = 0;
133 1.1 macallan sc->sc_msg_len = 0;
134 1.1 macallan
135 1.1 macallan ktm_init(sc);
136 1.1 macallan
137 1.1 macallan a.accessops = &ktm_accessops;
138 1.1 macallan a.accesscookie = sc;
139 1.1 macallan sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
140 1.1 macallan }
141 1.1 macallan
142 1.1 macallan static int
143 1.1 macallan ktm_turbo_csum(uint8_t *d)
144 1.1 macallan {
145 1.1 macallan int i = 0, sum = 0;
146 1.1 macallan
147 1.1 macallan for (i = 0; i < 7; i++)
148 1.1 macallan sum ^= d[i];
149 1.1 macallan return (sum ^ 0xff);
150 1.1 macallan }
151 1.1 macallan
152 1.1 macallan static void
153 1.1 macallan ktm_write_config(struct ktm_softc *sc)
154 1.1 macallan {
155 1.1 macallan uint8_t addr = sc->sc_adbdev->current_addr;
156 1.1 macallan
157 1.1 macallan ktm_send_sync(sc, ADBFLUSH(addr), 0, NULL);
158 1.1 macallan sc->sc_config[7] = ktm_turbo_csum(sc->sc_config);
159 1.1 macallan ktm_send_sync(sc, ADBLISTEN(addr, 2), 8, sc->sc_config);
160 1.1 macallan }
161 1.1 macallan
162 1.1 macallan static uint8_t button_to_reg[] = {0, 1, 4, 6};
163 1.1 macallan
164 1.1 macallan static void ktm_buttons(struct ktm_softc *sc)
165 1.1 macallan {
166 1.1 macallan uint8_t reg;
167 1.1 macallan
168 1.1 macallan reg = button_to_reg[sc->sc_right] |
169 1.1 macallan (button_to_reg[sc->sc_left] << 3);
170 1.1 macallan sc->sc_config[1] = reg;
171 1.1 macallan }
172 1.1 macallan
173 1.1 macallan static void
174 1.1 macallan ktm_init(struct ktm_softc *sc)
175 1.1 macallan {
176 1.1 macallan const struct sysctlnode *me = NULL, *node = NULL;
177 1.1 macallan int ret;
178 1.1 macallan uint8_t addr;
179 1.1 macallan
180 1.1 macallan /* Found Kensington Turbo Mouse */
181 1.1 macallan
182 1.1 macallan /*
183 1.1 macallan * byte 0
184 1.1 macallan - 0x80 enables EMP output
185 1.1 macallan - 0x08 seems to map both buttons together
186 1.1 macallan - 0x04 enables the 2nd button
187 1.1 macallan - initialized to 0x20 on power up, no idea what that does
188 1.1 macallan
189 1.1 macallan * byte 1 assigns what which button does
190 1.1 macallan - 0x08 - button 1 - 1, button 2 - nothing
191 1.1 macallan - 0x09 - both buttons - 1
192 1.1 macallan - 0x0a - butoon 1 - 1, button 2 - toggle 1
193 1.1 macallan - 0x0b - button 1 - 1, button 2 - nothing
194 1.1 macallan - 0x0c - button 1 - 1, button 2 - 2
195 1.1 macallan - 0x0e - button 1 - 1, button 2 - 3
196 1.1 macallan - 0x0f - button 1 - 1, button 2 - toggle 3
197 1.1 macallan - 0x10 - button 1 toggle 1, button 2 nothing
198 1.1 macallan - 0x11 - button 1 - toggle 1, button 2 - 1
199 1.1 macallan - 0x12 - both toggle 1
200 1.1 macallan - 0x14 - button 1 toggle 1, button 2 - 2
201 1.1 macallan - 0x21 - button 1 - 2, button 2 - 1
202 1.1 macallan - 0x31 - button 1 - 3, button 2 - 1
203 1.1 macallan
204 1.1 macallan * byte 2 - 0x40 on powerup, seems to do nothing
205 1.1 macallan * byte 3 - 0x01 on powerup, seems to do nothing
206 1.1 macallan * byte 4 programs a delay for button presses, apparently in 1/100 seconds
207 1.1 macallan * byte 5 and 6 init to 0xff
208 1.1 macallan * byte 7 is a simple XOR checksum, writes will only stick if it's valid
209 1.1 macallan as in, b[7] = (b[0] ^ b[1] ^ ... ^ b[6]) ^ 0xff
210 1.1 macallan */
211 1.1 macallan
212 1.1 macallan /* this seems to be the most reasonable default */
213 1.1 macallan uint8_t data[8] = { 0xa5, 0x0e, 0, 0, 1, 0xff, 0xff, 0 };
214 1.1 macallan
215 1.1 macallan addr = sc->sc_adbdev->current_addr;
216 1.1 macallan memcpy(sc->sc_config, data, sizeof(data));
217 1.1 macallan
218 1.1 macallan sc->sc_left = 1;
219 1.1 macallan sc->sc_right = 3;
220 1.1 macallan
221 1.1 macallan ktm_buttons(sc);
222 1.1 macallan
223 1.1 macallan #ifdef KTM_DEBUG
224 1.1 macallan {
225 1.1 macallan int i;
226 1.1 macallan ktm_send_sync(sc, ADBTALK(addr, 2), 0, NULL);
227 1.1 macallan printf("reg *");
228 1.1 macallan for (i = 0; i < sc->sc_msg_len; i++)
229 1.1 macallan printf(" %02x", sc->sc_buffer[i]);
230 1.1 macallan printf("\n");
231 1.1 macallan }
232 1.1 macallan #endif
233 1.1 macallan
234 1.1 macallan ktm_write_config(sc);
235 1.1 macallan
236 1.1 macallan #ifdef KTM_DEBUG
237 1.1 macallan int i, reg;
238 1.1 macallan for (reg = 1; reg < 4; reg++) {
239 1.1 macallan ktm_send_sync(sc, ADBTALK(addr, reg), 0, NULL);
240 1.1 macallan printf("reg %d", reg);
241 1.1 macallan for (i = 0; i < sc->sc_msg_len; i++)
242 1.1 macallan printf(" %02x", sc->sc_buffer[i]);
243 1.1 macallan printf("\n");
244 1.1 macallan }
245 1.1 macallan #endif
246 1.1 macallan ret = sysctl_createv(NULL, 0, NULL, &me,
247 1.1 macallan CTLFLAG_READWRITE,
248 1.1 macallan CTLTYPE_NODE, device_xname(sc->sc_dev), NULL,
249 1.1 macallan NULL, 0, NULL, 0,
250 1.1 macallan CTL_MACHDEP, CTL_CREATE, CTL_EOL);
251 1.1 macallan
252 1.1 macallan ret = sysctl_createv(NULL, 0, NULL, &node,
253 1.1 macallan CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
254 1.1 macallan CTLTYPE_INT, "left", "left button assigmnent",
255 1.1 macallan sysctl_ktm_left, 1, (void *)sc, 0,
256 1.1 macallan CTL_MACHDEP, me->sysctl_num, CTL_CREATE, CTL_EOL);
257 1.1 macallan
258 1.1 macallan ret = sysctl_createv(NULL, 0, NULL, &node,
259 1.1 macallan CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
260 1.1 macallan CTLTYPE_INT, "right", "right button assigmnent",
261 1.1 macallan sysctl_ktm_right, 1, (void *)sc, 0,
262 1.1 macallan CTL_MACHDEP, me->sysctl_num, CTL_CREATE, CTL_EOL);
263 1.1 macallan __USE(ret);
264 1.1 macallan }
265 1.1 macallan
266 1.1 macallan static void
267 1.1 macallan ktm_handler(void *cookie, int len, uint8_t *data)
268 1.1 macallan {
269 1.1 macallan struct ktm_softc *sc = cookie;
270 1.1 macallan
271 1.1 macallan #ifdef KTM_DEBUG
272 1.1 macallan int i;
273 1.1 macallan printf("%s: %02x - ", device_xname(sc->sc_dev), sc->sc_us);
274 1.1 macallan for (i = 0; i < len; i++) {
275 1.1 macallan printf(" %02x", data[i]);
276 1.1 macallan }
277 1.1 macallan printf("\n");
278 1.1 macallan #endif
279 1.1 macallan if (len >= 2) {
280 1.1 macallan memcpy(sc->sc_buffer, &data[2], len - 2);
281 1.1 macallan sc->sc_msg_len = len - 2;
282 1.1 macallan if (data[1] == sc->sc_us) {
283 1.1 macallan /* make sense of the mouse message */
284 1.1 macallan ktm_process_event(sc, sc->sc_msg_len, sc->sc_buffer);
285 1.1 macallan return;
286 1.1 macallan }
287 1.1 macallan wakeup(&sc->sc_event);
288 1.1 macallan } else {
289 1.1 macallan DPRINTF("bogus message\n");
290 1.1 macallan }
291 1.1 macallan }
292 1.1 macallan
293 1.1 macallan static void
294 1.1 macallan ktm_process_event(struct ktm_softc *sc, int len, uint8_t *buffer)
295 1.1 macallan {
296 1.1 macallan int buttons = 0, mask, dx, dy, i;
297 1.1 macallan int button_bit = 1;
298 1.1 macallan
299 1.1 macallan /* Classic Mouse Protocol (up to 2 buttons) */
300 1.1 macallan for (i = 0; i < 2; i++, button_bit <<= 1)
301 1.1 macallan /* 0 when button down */
302 1.1 macallan if (!(buffer[i] & 0x80))
303 1.1 macallan buttons |= button_bit;
304 1.1 macallan else
305 1.1 macallan buttons &= ~button_bit;
306 1.1 macallan /* Extended Protocol (up to 6 more buttons) */
307 1.1 macallan for (mask = 0x80; i < len;
308 1.1 macallan i += (mask == 0x80), button_bit <<= 1) {
309 1.1 macallan /* 0 when button down */
310 1.1 macallan if (!(buffer[i] & mask))
311 1.1 macallan buttons |= button_bit;
312 1.1 macallan else
313 1.1 macallan buttons &= ~button_bit;
314 1.1 macallan mask = ((mask >> 4) & 0xf) | ((mask & 0xf) << 4);
315 1.1 macallan }
316 1.1 macallan
317 1.1 macallan /* EMP crap, additional motion bits */
318 1.1 macallan int shift = 7, ddx, ddy, sign, smask;
319 1.1 macallan
320 1.1 macallan #ifdef KTM_DEBUG
321 1.1 macallan printf("EMP packet:");
322 1.1 macallan for (i = 0; i < len; i++)
323 1.1 macallan printf(" %02x", buffer[i]);
324 1.1 macallan printf("\n");
325 1.1 macallan #endif
326 1.1 macallan dx = (int)buffer[1] & 0x7f;
327 1.1 macallan dy = (int)buffer[0] & 0x7f;
328 1.1 macallan for (i = 2; i < len; i++) {
329 1.1 macallan ddx = (buffer[i] & 0x07);
330 1.1 macallan ddy = (buffer[i] & 0x70) >> 4;
331 1.1 macallan dx |= (ddx << shift);
332 1.1 macallan dy |= (ddy << shift);
333 1.1 macallan shift += 3;
334 1.1 macallan }
335 1.1 macallan sign = 1 << (shift - 1);
336 1.1 macallan smask = 0xffffffff << shift;
337 1.1 macallan if (dx & sign)
338 1.1 macallan dx |= smask;
339 1.1 macallan if (dy & sign)
340 1.1 macallan dy |= smask;
341 1.1 macallan #ifdef KTM_DEBUG
342 1.1 macallan printf("%d %d %08x %d\n", dx, dy, smask, shift);
343 1.1 macallan #endif
344 1.1 macallan
345 1.1 macallan if (sc->sc_wsmousedev)
346 1.1 macallan wsmouse_input(sc->sc_wsmousedev, buttons,
347 1.1 macallan dx, -dy, 0, 0,
348 1.1 macallan WSMOUSE_INPUT_DELTA);
349 1.1 macallan }
350 1.1 macallan
351 1.1 macallan static int
352 1.1 macallan ktm_enable(void *v)
353 1.1 macallan {
354 1.1 macallan return 0;
355 1.1 macallan }
356 1.1 macallan
357 1.1 macallan static int
358 1.1 macallan ktm_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
359 1.1 macallan {
360 1.1 macallan
361 1.1 macallan switch (cmd) {
362 1.1 macallan case WSMOUSEIO_GTYPE:
363 1.1 macallan *(u_int *)data = WSMOUSE_TYPE_ADB;
364 1.1 macallan break;
365 1.1 macallan
366 1.1 macallan default:
367 1.1 macallan return (EPASSTHROUGH);
368 1.1 macallan }
369 1.1 macallan return (0);
370 1.1 macallan }
371 1.1 macallan
372 1.1 macallan static void
373 1.1 macallan ktm_disable(void *v)
374 1.1 macallan {
375 1.1 macallan }
376 1.1 macallan
377 1.1 macallan static int
378 1.1 macallan ktm_wait(struct ktm_softc *sc, int timeout)
379 1.1 macallan {
380 1.1 macallan int cnt = 0;
381 1.1 macallan
382 1.1 macallan if (sc->sc_poll) {
383 1.1 macallan while (sc->sc_msg_len == -1) {
384 1.1 macallan sc->sc_ops->poll(sc->sc_ops->cookie);
385 1.1 macallan }
386 1.1 macallan } else {
387 1.1 macallan while ((sc->sc_msg_len == -1) && (cnt < timeout)) {
388 1.1 macallan tsleep(&sc->sc_event, 0, "ktmio", hz);
389 1.1 macallan cnt++;
390 1.1 macallan }
391 1.1 macallan }
392 1.1 macallan return (sc->sc_msg_len > 0);
393 1.1 macallan }
394 1.1 macallan
395 1.1 macallan static int
396 1.1 macallan ktm_send_sync(struct ktm_softc *sc, uint8_t cmd, int len, uint8_t *msg)
397 1.1 macallan {
398 1.1 macallan int i;
399 1.1 macallan
400 1.1 macallan sc->sc_msg_len = -1;
401 1.1 macallan DPRINTF("send: %02x", cmd);
402 1.1 macallan for (i = 0; i < len; i++)
403 1.1 macallan DPRINTF(" %02x", msg[i]);
404 1.1 macallan DPRINTF("\n");
405 1.1 macallan sc->sc_ops->send(sc->sc_ops->cookie, sc->sc_poll, cmd, len, msg);
406 1.1 macallan ktm_wait(sc, 3);
407 1.1 macallan return (sc->sc_msg_len != -1);
408 1.1 macallan }
409 1.1 macallan
410 1.1 macallan static int
411 1.1 macallan sysctl_ktm_left(SYSCTLFN_ARGS)
412 1.1 macallan {
413 1.1 macallan struct sysctlnode node = *rnode;
414 1.1 macallan struct ktm_softc *sc = node.sysctl_data;
415 1.1 macallan int reg = sc->sc_left;
416 1.1 macallan
417 1.1 macallan if (newp) {
418 1.1 macallan
419 1.1 macallan /* we're asked to write */
420 1.1 macallan node.sysctl_data = ®
421 1.1 macallan if (sysctl_lookup(SYSCTLFN_CALL(&node)) == 0) {
422 1.1 macallan
423 1.1 macallan reg = *(int *)node.sysctl_data;
424 1.1 macallan if ((reg != sc->sc_left) &&
425 1.1 macallan (reg >= 0) &&
426 1.1 macallan (reg < 4)) {
427 1.1 macallan sc->sc_left = reg;
428 1.1 macallan ktm_buttons(sc);
429 1.1 macallan ktm_write_config(sc);
430 1.1 macallan }
431 1.1 macallan return 0;
432 1.1 macallan }
433 1.1 macallan return EINVAL;
434 1.1 macallan } else {
435 1.1 macallan
436 1.1 macallan node.sysctl_data = ®
437 1.1 macallan node.sysctl_size = 4;
438 1.1 macallan return (sysctl_lookup(SYSCTLFN_CALL(&node)));
439 1.1 macallan }
440 1.1 macallan
441 1.1 macallan return 0;
442 1.1 macallan }
443 1.1 macallan
444 1.1 macallan static int
445 1.1 macallan sysctl_ktm_right(SYSCTLFN_ARGS)
446 1.1 macallan {
447 1.1 macallan struct sysctlnode node = *rnode;
448 1.1 macallan struct ktm_softc *sc = node.sysctl_data;
449 1.1 macallan int reg = sc->sc_right;
450 1.1 macallan
451 1.1 macallan if (newp) {
452 1.1 macallan
453 1.1 macallan /* we're asked to write */
454 1.1 macallan node.sysctl_data = ®
455 1.1 macallan if (sysctl_lookup(SYSCTLFN_CALL(&node)) == 0) {
456 1.1 macallan
457 1.1 macallan reg = *(int *)node.sysctl_data;
458 1.1 macallan if ((reg != sc->sc_right) &&
459 1.1 macallan (reg >= 0) &&
460 1.1 macallan (reg < 4)) {
461 1.1 macallan sc->sc_right = reg;
462 1.1 macallan ktm_buttons(sc);
463 1.1 macallan ktm_write_config(sc);
464 1.1 macallan }
465 1.1 macallan return 0;
466 1.1 macallan }
467 1.1 macallan return EINVAL;
468 1.1 macallan } else {
469 1.1 macallan
470 1.1 macallan node.sysctl_data = ®
471 1.1 macallan node.sysctl_size = 4;
472 1.1 macallan return (sysctl_lookup(SYSCTLFN_CALL(&node)));
473 1.1 macallan }
474 1.1 macallan
475 1.1 macallan return 0;
476 1.1 macallan }
477 1.1 macallan
478 1.1 macallan SYSCTL_SETUP(sysctl_ktm_setup, "sysctl ktm subtree setup")
479 1.1 macallan {
480 1.1 macallan
481 1.1 macallan sysctl_createv(NULL, 0, NULL, NULL,
482 1.1 macallan CTLFLAG_PERMANENT,
483 1.1 macallan CTLTYPE_NODE, "machdep", NULL,
484 1.1 macallan NULL, 0, NULL, 0,
485 1.1 macallan CTL_MACHDEP, CTL_EOL);
486 1.1 macallan }
487