1 1.9 macallan /* $NetBSD: adb_ktm.c,v 1.9 2025/06/16 07:51:16 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.9 macallan __KERNEL_RCSID(0, "$NetBSD: adb_ktm.c,v 1.9 2025/06/16 07:51:16 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/sysctl.h> 35 1.9 macallan #include <sys/condvar.h> 36 1.1 macallan 37 1.1 macallan #include <machine/autoconf.h> 38 1.1 macallan 39 1.1 macallan #include <dev/wscons/wsconsio.h> 40 1.1 macallan #include <dev/wscons/wsmousevar.h> 41 1.1 macallan 42 1.1 macallan #include <dev/adb/adbvar.h> 43 1.1 macallan 44 1.1 macallan #include "adbdebug.h" 45 1.1 macallan 46 1.1 macallan #ifdef KTM_DEBUG 47 1.1 macallan #define DPRINTF printf 48 1.1 macallan #else 49 1.1 macallan #define DPRINTF while (0) printf 50 1.1 macallan #endif 51 1.1 macallan 52 1.1 macallan /* 53 1.1 macallan * State info, per mouse instance. 54 1.1 macallan */ 55 1.1 macallan struct ktm_softc { 56 1.1 macallan device_t sc_dev; 57 1.1 macallan struct adb_device *sc_adbdev; 58 1.1 macallan struct adb_bus_accessops *sc_ops; 59 1.1 macallan 60 1.1 macallan uint8_t sc_us; /* cmd to watch for */ 61 1.1 macallan device_t sc_wsmousedev; 62 1.1 macallan /* buffers */ 63 1.1 macallan uint8_t sc_config[8]; 64 1.1 macallan int sc_left; 65 1.1 macallan int sc_right; 66 1.1 macallan int sc_poll; 67 1.1 macallan int sc_msg_len; 68 1.9 macallan kcondvar_t sc_event; 69 1.9 macallan kmutex_t sc_interlock; 70 1.1 macallan uint8_t sc_buffer[16]; 71 1.1 macallan }; 72 1.1 macallan 73 1.1 macallan /* 74 1.1 macallan * Function declarations. 75 1.1 macallan */ 76 1.1 macallan static int ktm_match(device_t, cfdata_t, void *); 77 1.1 macallan static void ktm_attach(device_t, device_t, void *); 78 1.1 macallan static void ktm_init(struct ktm_softc *); 79 1.1 macallan static void ktm_write_config(struct ktm_softc *); 80 1.1 macallan static void ktm_buttons(struct ktm_softc *); 81 1.1 macallan static void ktm_process_event(struct ktm_softc *, int, uint8_t *); 82 1.1 macallan static int ktm_send_sync(struct ktm_softc *, uint8_t, int, uint8_t *); 83 1.1 macallan 84 1.1 macallan /* Driver definition. */ 85 1.1 macallan CFATTACH_DECL_NEW(ktm, sizeof(struct ktm_softc), 86 1.1 macallan ktm_match, ktm_attach, NULL, NULL); 87 1.1 macallan 88 1.1 macallan static int ktm_enable(void *); 89 1.1 macallan static int ktm_ioctl(void *, u_long, void *, int, struct lwp *); 90 1.1 macallan static void ktm_disable(void *); 91 1.1 macallan 92 1.1 macallan static void ktm_handler(void *, int, uint8_t *); 93 1.1 macallan static int ktm_wait(struct ktm_softc *, int); 94 1.1 macallan static int sysctl_ktm_left(SYSCTLFN_ARGS); 95 1.1 macallan static int sysctl_ktm_right(SYSCTLFN_ARGS); 96 1.1 macallan 97 1.1 macallan const struct wsmouse_accessops ktm_accessops = { 98 1.1 macallan ktm_enable, 99 1.1 macallan ktm_ioctl, 100 1.1 macallan ktm_disable, 101 1.1 macallan }; 102 1.1 macallan 103 1.1 macallan static int 104 1.1 macallan ktm_match(device_t parent, cfdata_t cf, void *aux) 105 1.1 macallan { 106 1.1 macallan struct adb_attach_args *aaa = aux; 107 1.1 macallan if ((aaa->dev->original_addr == ADBADDR_MS) && 108 1.1 macallan (aaa->dev->handler_id == ADBMS_TURBO)) 109 1.1 macallan return 50; /* beat out adbms */ 110 1.1 macallan else 111 1.1 macallan return 0; 112 1.1 macallan } 113 1.1 macallan 114 1.1 macallan static void 115 1.1 macallan ktm_attach(device_t parent, device_t self, void *aux) 116 1.1 macallan { 117 1.1 macallan struct ktm_softc *sc = device_private(self); 118 1.1 macallan struct adb_attach_args *aaa = aux; 119 1.1 macallan struct wsmousedev_attach_args a; 120 1.1 macallan 121 1.1 macallan sc->sc_dev = self; 122 1.1 macallan sc->sc_ops = aaa->ops; 123 1.1 macallan sc->sc_adbdev = aaa->dev; 124 1.1 macallan sc->sc_adbdev->cookie = sc; 125 1.1 macallan sc->sc_adbdev->handler = ktm_handler; 126 1.9 macallan mutex_init(&sc->sc_interlock, MUTEX_DEFAULT, IPL_NONE); 127 1.9 macallan cv_init(&sc->sc_event, "ktm"); 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.4 thorpej sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint, CFARGS_NONE); 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 179 1.1 macallan /* Found Kensington Turbo Mouse */ 180 1.1 macallan 181 1.1 macallan /* 182 1.1 macallan * byte 0 183 1.1 macallan - 0x80 enables EMP output 184 1.1 macallan - 0x08 seems to map both buttons together 185 1.1 macallan - 0x04 enables the 2nd button 186 1.1 macallan - initialized to 0x20 on power up, no idea what that does 187 1.1 macallan 188 1.1 macallan * byte 1 assigns what which button does 189 1.1 macallan - 0x08 - button 1 - 1, button 2 - nothing 190 1.1 macallan - 0x09 - both buttons - 1 191 1.7 andvar - 0x0a - button 1 - 1, button 2 - toggle 1 192 1.1 macallan - 0x0b - button 1 - 1, button 2 - nothing 193 1.1 macallan - 0x0c - button 1 - 1, button 2 - 2 194 1.1 macallan - 0x0e - button 1 - 1, button 2 - 3 195 1.1 macallan - 0x0f - button 1 - 1, button 2 - toggle 3 196 1.1 macallan - 0x10 - button 1 toggle 1, button 2 nothing 197 1.1 macallan - 0x11 - button 1 - toggle 1, button 2 - 1 198 1.1 macallan - 0x12 - both toggle 1 199 1.1 macallan - 0x14 - button 1 toggle 1, button 2 - 2 200 1.1 macallan - 0x21 - button 1 - 2, button 2 - 1 201 1.1 macallan - 0x31 - button 1 - 3, button 2 - 1 202 1.1 macallan 203 1.1 macallan * byte 2 - 0x40 on powerup, seems to do nothing 204 1.1 macallan * byte 3 - 0x01 on powerup, seems to do nothing 205 1.1 macallan * byte 4 programs a delay for button presses, apparently in 1/100 seconds 206 1.1 macallan * byte 5 and 6 init to 0xff 207 1.1 macallan * byte 7 is a simple XOR checksum, writes will only stick if it's valid 208 1.1 macallan as in, b[7] = (b[0] ^ b[1] ^ ... ^ b[6]) ^ 0xff 209 1.1 macallan */ 210 1.1 macallan 211 1.1 macallan /* this seems to be the most reasonable default */ 212 1.1 macallan uint8_t data[8] = { 0xa5, 0x0e, 0, 0, 1, 0xff, 0xff, 0 }; 213 1.1 macallan 214 1.1 macallan memcpy(sc->sc_config, data, sizeof(data)); 215 1.1 macallan 216 1.1 macallan sc->sc_left = 1; 217 1.1 macallan sc->sc_right = 3; 218 1.1 macallan 219 1.1 macallan ktm_buttons(sc); 220 1.1 macallan 221 1.1 macallan #ifdef KTM_DEBUG 222 1.2 macallan int addr = sc->sc_adbdev->current_addr; 223 1.1 macallan { 224 1.1 macallan int i; 225 1.1 macallan ktm_send_sync(sc, ADBTALK(addr, 2), 0, NULL); 226 1.1 macallan printf("reg *"); 227 1.1 macallan for (i = 0; i < sc->sc_msg_len; i++) 228 1.1 macallan printf(" %02x", sc->sc_buffer[i]); 229 1.1 macallan printf("\n"); 230 1.1 macallan } 231 1.1 macallan #endif 232 1.1 macallan 233 1.1 macallan ktm_write_config(sc); 234 1.1 macallan 235 1.1 macallan #ifdef KTM_DEBUG 236 1.1 macallan int i, reg; 237 1.1 macallan for (reg = 1; reg < 4; reg++) { 238 1.1 macallan ktm_send_sync(sc, ADBTALK(addr, reg), 0, NULL); 239 1.1 macallan printf("reg %d", reg); 240 1.1 macallan for (i = 0; i < sc->sc_msg_len; i++) 241 1.1 macallan printf(" %02x", sc->sc_buffer[i]); 242 1.1 macallan printf("\n"); 243 1.1 macallan } 244 1.1 macallan #endif 245 1.1 macallan ret = sysctl_createv(NULL, 0, NULL, &me, 246 1.1 macallan CTLFLAG_READWRITE, 247 1.1 macallan CTLTYPE_NODE, device_xname(sc->sc_dev), NULL, 248 1.1 macallan NULL, 0, NULL, 0, 249 1.1 macallan CTL_MACHDEP, CTL_CREATE, CTL_EOL); 250 1.1 macallan 251 1.1 macallan ret = sysctl_createv(NULL, 0, NULL, &node, 252 1.1 macallan CTLFLAG_READWRITE | CTLFLAG_OWNDESC, 253 1.6 andvar CTLTYPE_INT, "left", "left button assignment", 254 1.1 macallan sysctl_ktm_left, 1, (void *)sc, 0, 255 1.1 macallan CTL_MACHDEP, me->sysctl_num, CTL_CREATE, CTL_EOL); 256 1.1 macallan 257 1.1 macallan ret = sysctl_createv(NULL, 0, NULL, &node, 258 1.1 macallan CTLFLAG_READWRITE | CTLFLAG_OWNDESC, 259 1.6 andvar CTLTYPE_INT, "right", "right button assignment", 260 1.1 macallan sysctl_ktm_right, 1, (void *)sc, 0, 261 1.1 macallan CTL_MACHDEP, me->sysctl_num, CTL_CREATE, CTL_EOL); 262 1.1 macallan __USE(ret); 263 1.1 macallan } 264 1.1 macallan 265 1.1 macallan static void 266 1.1 macallan ktm_handler(void *cookie, int len, uint8_t *data) 267 1.1 macallan { 268 1.1 macallan struct ktm_softc *sc = cookie; 269 1.1 macallan 270 1.1 macallan #ifdef KTM_DEBUG 271 1.1 macallan int i; 272 1.1 macallan printf("%s: %02x - ", device_xname(sc->sc_dev), sc->sc_us); 273 1.1 macallan for (i = 0; i < len; i++) { 274 1.1 macallan printf(" %02x", data[i]); 275 1.1 macallan } 276 1.1 macallan printf("\n"); 277 1.1 macallan #endif 278 1.1 macallan if (len >= 2) { 279 1.1 macallan memcpy(sc->sc_buffer, &data[2], len - 2); 280 1.1 macallan sc->sc_msg_len = len - 2; 281 1.1 macallan if (data[1] == sc->sc_us) { 282 1.1 macallan /* make sense of the mouse message */ 283 1.1 macallan ktm_process_event(sc, sc->sc_msg_len, sc->sc_buffer); 284 1.1 macallan return; 285 1.1 macallan } 286 1.9 macallan cv_signal(&sc->sc_event); 287 1.1 macallan } else { 288 1.1 macallan DPRINTF("bogus message\n"); 289 1.1 macallan } 290 1.1 macallan } 291 1.1 macallan 292 1.1 macallan static void 293 1.1 macallan ktm_process_event(struct ktm_softc *sc, int len, uint8_t *buffer) 294 1.1 macallan { 295 1.1 macallan int buttons = 0, mask, dx, dy, i; 296 1.1 macallan int button_bit = 1; 297 1.1 macallan 298 1.1 macallan /* Classic Mouse Protocol (up to 2 buttons) */ 299 1.1 macallan for (i = 0; i < 2; i++, button_bit <<= 1) 300 1.1 macallan /* 0 when button down */ 301 1.1 macallan if (!(buffer[i] & 0x80)) 302 1.1 macallan buttons |= button_bit; 303 1.1 macallan else 304 1.1 macallan buttons &= ~button_bit; 305 1.1 macallan /* Extended Protocol (up to 6 more buttons) */ 306 1.1 macallan for (mask = 0x80; i < len; 307 1.1 macallan i += (mask == 0x80), button_bit <<= 1) { 308 1.1 macallan /* 0 when button down */ 309 1.1 macallan if (!(buffer[i] & mask)) 310 1.1 macallan buttons |= button_bit; 311 1.1 macallan else 312 1.1 macallan buttons &= ~button_bit; 313 1.1 macallan mask = ((mask >> 4) & 0xf) | ((mask & 0xf) << 4); 314 1.1 macallan } 315 1.1 macallan 316 1.1 macallan /* EMP crap, additional motion bits */ 317 1.1 macallan int shift = 7, ddx, ddy, sign, smask; 318 1.1 macallan 319 1.1 macallan #ifdef KTM_DEBUG 320 1.1 macallan printf("EMP packet:"); 321 1.1 macallan for (i = 0; i < len; i++) 322 1.1 macallan printf(" %02x", buffer[i]); 323 1.1 macallan printf("\n"); 324 1.1 macallan #endif 325 1.1 macallan dx = (int)buffer[1] & 0x7f; 326 1.1 macallan dy = (int)buffer[0] & 0x7f; 327 1.1 macallan for (i = 2; i < len; i++) { 328 1.1 macallan ddx = (buffer[i] & 0x07); 329 1.1 macallan ddy = (buffer[i] & 0x70) >> 4; 330 1.1 macallan dx |= (ddx << shift); 331 1.1 macallan dy |= (ddy << shift); 332 1.1 macallan shift += 3; 333 1.1 macallan } 334 1.1 macallan sign = 1 << (shift - 1); 335 1.1 macallan smask = 0xffffffff << shift; 336 1.1 macallan if (dx & sign) 337 1.1 macallan dx |= smask; 338 1.1 macallan if (dy & sign) 339 1.1 macallan dy |= smask; 340 1.1 macallan #ifdef KTM_DEBUG 341 1.1 macallan printf("%d %d %08x %d\n", dx, dy, smask, shift); 342 1.1 macallan #endif 343 1.1 macallan 344 1.1 macallan if (sc->sc_wsmousedev) 345 1.1 macallan wsmouse_input(sc->sc_wsmousedev, buttons, 346 1.1 macallan dx, -dy, 0, 0, 347 1.1 macallan WSMOUSE_INPUT_DELTA); 348 1.1 macallan } 349 1.1 macallan 350 1.1 macallan static int 351 1.1 macallan ktm_enable(void *v) 352 1.1 macallan { 353 1.1 macallan return 0; 354 1.1 macallan } 355 1.1 macallan 356 1.1 macallan static int 357 1.1 macallan ktm_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l) 358 1.1 macallan { 359 1.1 macallan 360 1.1 macallan switch (cmd) { 361 1.1 macallan case WSMOUSEIO_GTYPE: 362 1.1 macallan *(u_int *)data = WSMOUSE_TYPE_ADB; 363 1.1 macallan break; 364 1.1 macallan 365 1.1 macallan default: 366 1.5 macallan return EPASSTHROUGH; 367 1.1 macallan } 368 1.5 macallan return 0; 369 1.1 macallan } 370 1.1 macallan 371 1.1 macallan static void 372 1.1 macallan ktm_disable(void *v) 373 1.1 macallan { 374 1.1 macallan } 375 1.1 macallan 376 1.1 macallan static int 377 1.1 macallan ktm_wait(struct ktm_softc *sc, int timeout) 378 1.1 macallan { 379 1.1 macallan int cnt = 0; 380 1.1 macallan 381 1.1 macallan if (sc->sc_poll) { 382 1.1 macallan while (sc->sc_msg_len == -1) { 383 1.1 macallan sc->sc_ops->poll(sc->sc_ops->cookie); 384 1.1 macallan } 385 1.1 macallan } else { 386 1.9 macallan mutex_enter(&sc->sc_interlock); 387 1.1 macallan while ((sc->sc_msg_len == -1) && (cnt < timeout)) { 388 1.9 macallan cv_timedwait(&sc->sc_event, &sc->sc_interlock, hz); 389 1.1 macallan cnt++; 390 1.1 macallan } 391 1.9 macallan mutex_exit(&sc->sc_interlock); 392 1.1 macallan } 393 1.1 macallan return (sc->sc_msg_len > 0); 394 1.1 macallan } 395 1.1 macallan 396 1.1 macallan static int 397 1.1 macallan ktm_send_sync(struct ktm_softc *sc, uint8_t cmd, int len, uint8_t *msg) 398 1.1 macallan { 399 1.1 macallan int i; 400 1.1 macallan 401 1.1 macallan sc->sc_msg_len = -1; 402 1.1 macallan DPRINTF("send: %02x", cmd); 403 1.1 macallan for (i = 0; i < len; i++) 404 1.1 macallan DPRINTF(" %02x", msg[i]); 405 1.1 macallan DPRINTF("\n"); 406 1.1 macallan sc->sc_ops->send(sc->sc_ops->cookie, sc->sc_poll, cmd, len, msg); 407 1.1 macallan ktm_wait(sc, 3); 408 1.1 macallan return (sc->sc_msg_len != -1); 409 1.1 macallan } 410 1.1 macallan 411 1.1 macallan static int 412 1.1 macallan sysctl_ktm_left(SYSCTLFN_ARGS) 413 1.1 macallan { 414 1.1 macallan struct sysctlnode node = *rnode; 415 1.1 macallan struct ktm_softc *sc = node.sysctl_data; 416 1.1 macallan int reg = sc->sc_left; 417 1.1 macallan 418 1.1 macallan if (newp) { 419 1.1 macallan 420 1.1 macallan /* we're asked to write */ 421 1.1 macallan node.sysctl_data = ® 422 1.1 macallan if (sysctl_lookup(SYSCTLFN_CALL(&node)) == 0) { 423 1.1 macallan 424 1.1 macallan reg = *(int *)node.sysctl_data; 425 1.1 macallan if ((reg != sc->sc_left) && 426 1.1 macallan (reg >= 0) && 427 1.1 macallan (reg < 4)) { 428 1.1 macallan sc->sc_left = reg; 429 1.1 macallan ktm_buttons(sc); 430 1.1 macallan ktm_write_config(sc); 431 1.1 macallan } 432 1.1 macallan return 0; 433 1.1 macallan } 434 1.1 macallan return EINVAL; 435 1.1 macallan } else { 436 1.1 macallan 437 1.1 macallan node.sysctl_data = ® 438 1.1 macallan node.sysctl_size = 4; 439 1.1 macallan return (sysctl_lookup(SYSCTLFN_CALL(&node))); 440 1.1 macallan } 441 1.1 macallan 442 1.1 macallan return 0; 443 1.1 macallan } 444 1.1 macallan 445 1.1 macallan static int 446 1.1 macallan sysctl_ktm_right(SYSCTLFN_ARGS) 447 1.1 macallan { 448 1.1 macallan struct sysctlnode node = *rnode; 449 1.1 macallan struct ktm_softc *sc = node.sysctl_data; 450 1.1 macallan int reg = sc->sc_right; 451 1.1 macallan 452 1.1 macallan if (newp) { 453 1.1 macallan 454 1.1 macallan /* we're asked to write */ 455 1.1 macallan node.sysctl_data = ® 456 1.1 macallan if (sysctl_lookup(SYSCTLFN_CALL(&node)) == 0) { 457 1.1 macallan 458 1.1 macallan reg = *(int *)node.sysctl_data; 459 1.1 macallan if ((reg != sc->sc_right) && 460 1.1 macallan (reg >= 0) && 461 1.1 macallan (reg < 4)) { 462 1.1 macallan sc->sc_right = reg; 463 1.1 macallan ktm_buttons(sc); 464 1.1 macallan ktm_write_config(sc); 465 1.1 macallan } 466 1.1 macallan return 0; 467 1.1 macallan } 468 1.1 macallan return EINVAL; 469 1.1 macallan } else { 470 1.1 macallan 471 1.1 macallan node.sysctl_data = ® 472 1.1 macallan node.sysctl_size = 4; 473 1.1 macallan return (sysctl_lookup(SYSCTLFN_CALL(&node))); 474 1.1 macallan } 475 1.1 macallan 476 1.1 macallan return 0; 477 1.1 macallan } 478 1.1 macallan 479 1.1 macallan SYSCTL_SETUP(sysctl_ktm_setup, "sysctl ktm subtree setup") 480 1.1 macallan { 481 1.1 macallan 482 1.1 macallan sysctl_createv(NULL, 0, NULL, NULL, 483 1.1 macallan CTLFLAG_PERMANENT, 484 1.1 macallan CTLTYPE_NODE, "machdep", NULL, 485 1.1 macallan NULL, 0, NULL, 0, 486 1.1 macallan CTL_MACHDEP, CTL_EOL); 487 1.1 macallan } 488