1 /* $NetBSD: aed.c,v 1.44 2026/05/23 20:56:32 nat Exp $ */ 2 3 /* 4 * Copyright (c) 2024, 2026 Nathanial Sloss <nathanialsloss (at) yahoo.com.au> 5 * All rights reserved. 6 * 7 * Copyright (C) 1994 Bradley A. Grantham 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: aed.c,v 1.44 2026/05/23 20:56:32 nat Exp $"); 33 34 #include "opt_adb.h" 35 36 #include <sys/param.h> 37 #include <sys/device.h> 38 #include <sys/fcntl.h> 39 #include <sys/poll.h> 40 #include <sys/select.h> 41 #include <sys/proc.h> 42 #include <sys/signalvar.h> 43 #include <sys/systm.h> 44 #include <sys/conf.h> 45 46 #include <machine/autoconf.h> 47 #include <machine/cpu.h> 48 #include <machine/keyboard.h> 49 50 #include <mac68k/mac68k/macrom.h> 51 #include <mac68k/dev/adbvar.h> 52 #include <mac68k/dev/aedvar.h> 53 #include <mac68k/dev/akbdvar.h> 54 #include <mac68k/dev/pm_direct.h> 55 56 #define BRIGHTNESS_MAX 31 57 #define BRIGHTNESS_MIN 0 58 #define BRIGHTNESS_STEP 4 59 60 #if defined(ALTXBUTTONS) && defined(EMULFKEYS) 61 #error "options ALTXBUTTONS" and "options EMULFKEYS" cannot be used together. 62 #endif 63 64 /* 65 * Function declarations. 66 */ 67 static int aedmatch(device_t, cfdata_t, void *); 68 static void aedattach(device_t, device_t, void *); 69 static int aed_emulate_mouse(adb_event_t *); 70 static void aed_kbdrpt(void *); 71 static void aed_dokeyupdown(adb_event_t *); 72 static void aed_handoff(adb_event_t *); 73 static void aed_enqevent(adb_event_t *); 74 75 static void aed_display_on(device_t); 76 static void aed_display_off(device_t); 77 static void aed_brightness_down(device_t); 78 static void aed_brightness_up(device_t); 79 80 /* 81 * Local variables. 82 */ 83 static struct aed_softc *aed_sc; 84 static int aed_options = 0 | AED_MSEMUL; 85 static int brightness = BRIGHTNESS_MAX; 86 87 /* Driver definition */ 88 CFATTACH_DECL_NEW(aed, sizeof(struct aed_softc), 89 aedmatch, aedattach, NULL, NULL); 90 91 extern struct cfdriver aed_cd; 92 93 dev_type_open(aedopen); 94 dev_type_close(aedclose); 95 dev_type_read(aedread); 96 dev_type_ioctl(aedioctl); 97 dev_type_poll(aedpoll); 98 dev_type_kqfilter(aedkqfilter); 99 100 const struct cdevsw aed_cdevsw = { 101 .d_open = aedopen, 102 .d_close = aedclose, 103 .d_read = aedread, 104 .d_write = nullwrite, 105 .d_ioctl = aedioctl, 106 .d_stop = nostop, 107 .d_tty = notty, 108 .d_poll = aedpoll, 109 .d_mmap = nommap, 110 .d_kqfilter = aedkqfilter, 111 .d_discard = nodiscard, 112 .d_flag = 0 113 }; 114 115 static int 116 aedmatch(device_t parent, cfdata_t cf, void *aux) 117 { 118 struct adb_attach_args *aa_args = (struct adb_attach_args *)aux; 119 static int aed_matched; 120 121 /* Allow only one instance. */ 122 if ((aa_args->origaddr == 0) && (!aed_matched)) { 123 aed_matched = 1; 124 return (1); 125 } else 126 return (0); 127 } 128 129 static void 130 aedattach(device_t parent, device_t self, void *aux) 131 { 132 struct adb_attach_args *aa_args = (struct adb_attach_args *)aux; 133 struct aed_softc *sc = device_private(self); 134 135 callout_init(&sc->sc_repeat_ch, 0); 136 selinit(&sc->sc_selinfo); 137 138 sc->origaddr = aa_args->origaddr; 139 sc->adbaddr = aa_args->adbaddr; 140 sc->handler_id = aa_args->handler_id; 141 142 sc->sc_evq_tail = 0; 143 sc->sc_evq_len = 0; 144 145 sc->sc_rptdelay = 20; 146 sc->sc_rptinterval = 6; 147 sc->sc_repeating = -1; /* not repeating */ 148 149 /* Pull in the options flags. */ 150 sc->sc_options = (device_cfdata(self)->cf_flags | aed_options); 151 152 sc->sc_ioproc = NULL; 153 154 sc->sc_buttons = 0; 155 156 sc->sc_open = 0; 157 158 aed_sc = sc; 159 160 pmf_event_register(self, PMFE_DISPLAY_ON, 161 aed_display_on, TRUE); 162 pmf_event_register(self, PMFE_DISPLAY_OFF, 163 aed_display_off, TRUE); 164 pmf_event_register(self, PMFE_DISPLAY_BRIGHTNESS_UP, 165 aed_brightness_up, TRUE); 166 pmf_event_register(self, PMFE_DISPLAY_BRIGHTNESS_DOWN, 167 aed_brightness_down, TRUE); 168 169 printf("ADB Event device\n"); 170 171 #if 1 172 (void)config_found(self, &aa_args, NULL, CFARGS_NONE); 173 #endif 174 175 return; 176 } 177 178 /* 179 * Given a keyboard ADB event, record the keycode and call the key 180 * repeat handler, optionally passing the event through the mouse 181 * button emulation handler first. Pass mouse events directly to 182 * the handoff function. 183 */ 184 int 185 aed_input(adb_event_t *event) 186 { 187 adb_event_t new_event = *event; 188 int rv = aed_sc->sc_open; 189 190 switch (event->def_addr) { 191 case ADBADDR_KBD: 192 if (aed_sc->sc_options & AED_MSEMUL) { 193 rv = aed_emulate_mouse(&new_event); 194 /* Pass up function key emultion to keyboard driver */ 195 if (rv == 2) { 196 memcpy(event, &new_event, sizeof(new_event)); 197 rv = 0; 198 } 199 } else 200 aed_dokeyupdown(&new_event); 201 break; 202 case ADBADDR_MS: 203 event->u.m.buttons |= aed_sc->sc_buttons; 204 new_event.u.m.buttons |= aed_sc->sc_buttons; 205 aed_handoff(&new_event); 206 break; 207 default: /* God only knows. */ 208 #ifdef DIAGNOSTIC 209 panic("aed: received event from unsupported device!"); 210 #endif 211 rv = 0; 212 break; 213 } 214 215 return (rv); 216 } 217 218 /* 219 * Handles mouse button emulation via the keyboard. If the emulation 220 * modifier key is down, left and right arrows will generate 2nd and 221 * 3rd mouse button events while the 1, 2, and 3 keys will generate 222 * the corresponding mouse button event. 223 */ 224 static int 225 aed_emulate_mouse(adb_event_t *event) 226 { 227 static int emulmodkey_down; 228 adb_event_t new_event; 229 int result = 0; 230 231 if (event->u.k.key == ADBK_KEYDOWN(ADBK_OPTION)) { 232 emulmodkey_down = 1; 233 } else if (event->u.k.key == ADBK_KEYUP(ADBK_OPTION)) { 234 /* key up */ 235 emulmodkey_down = 0; 236 if (aed_sc->sc_buttons & 0xfe) { 237 aed_sc->sc_buttons &= 1; 238 new_event.def_addr = ADBADDR_MS; 239 new_event.u.m.buttons = aed_sc->sc_buttons; 240 new_event.u.m.dx = new_event.u.m.dy = 0; 241 microtime(&new_event.timestamp); 242 aed_handoff(&new_event); 243 } 244 } else if (emulmodkey_down) { 245 #if defined(EMULFKEYS) 246 int fkey = 0; 247 #endif 248 switch(event->u.k.key) { 249 #ifdef ALTXBUTTONS 250 case ADBK_KEYDOWN(ADBK_1): 251 result = 1; 252 aed_sc->sc_buttons |= 1; /* left down */ 253 new_event.def_addr = ADBADDR_MS; 254 new_event.u.m.buttons = aed_sc->sc_buttons; 255 new_event.u.m.dx = new_event.u.m.dy = 0; 256 microtime(&new_event.timestamp); 257 aed_handoff(&new_event); 258 break; 259 case ADBK_KEYUP(ADBK_1): 260 result = 1; 261 aed_sc->sc_buttons &= ~1; /* left up */ 262 new_event.def_addr = ADBADDR_MS; 263 new_event.u.m.buttons = aed_sc->sc_buttons; 264 new_event.u.m.dx = new_event.u.m.dy = 0; 265 microtime(&new_event.timestamp); 266 aed_handoff(&new_event); 267 break; 268 #endif 269 case ADBK_KEYDOWN(ADBK_LEFT): 270 #ifdef ALTXBUTTONS 271 case ADBK_KEYDOWN(ADBK_2): 272 #endif 273 result = 1; 274 aed_sc->sc_buttons |= 2; /* middle down */ 275 new_event.def_addr = ADBADDR_MS; 276 new_event.u.m.buttons = aed_sc->sc_buttons; 277 new_event.u.m.dx = new_event.u.m.dy = 0; 278 microtime(&new_event.timestamp); 279 aed_handoff(&new_event); 280 break; 281 case ADBK_KEYUP(ADBK_LEFT): 282 #ifdef ALTXBUTTONS 283 case ADBK_KEYUP(ADBK_2): 284 #endif 285 result = 1; 286 aed_sc->sc_buttons &= ~2; /* middle up */ 287 new_event.def_addr = ADBADDR_MS; 288 new_event.u.m.buttons = aed_sc->sc_buttons; 289 new_event.u.m.dx = new_event.u.m.dy = 0; 290 microtime(&new_event.timestamp); 291 aed_handoff(&new_event); 292 break; 293 case ADBK_KEYDOWN(ADBK_RIGHT): 294 #ifdef ALTXBUTTONS 295 case ADBK_KEYDOWN(ADBK_3): 296 #endif 297 result = 1; 298 aed_sc->sc_buttons |= 4; /* right down */ 299 new_event.def_addr = ADBADDR_MS; 300 new_event.u.m.buttons = aed_sc->sc_buttons; 301 new_event.u.m.dx = new_event.u.m.dy = 0; 302 microtime(&new_event.timestamp); 303 aed_handoff(&new_event); 304 break; 305 case ADBK_KEYUP(ADBK_RIGHT): 306 #ifdef ALTXBUTTONS 307 case ADBK_KEYUP(ADBK_3): 308 #endif 309 result = 1; 310 aed_sc->sc_buttons &= ~4; /* right up */ 311 new_event.def_addr = ADBADDR_MS; 312 new_event.u.m.buttons = aed_sc->sc_buttons; 313 new_event.u.m.dx = new_event.u.m.dy = 0; 314 microtime(&new_event.timestamp); 315 aed_handoff(&new_event); 316 break; 317 case ADBK_KEYDOWN(ADBK_UP): 318 result = 1; 319 break; 320 case ADBK_KEYUP(ADBK_UP): 321 result = 1; 322 pmf_event_inject(NULL, PMFE_DISPLAY_BRIGHTNESS_UP); 323 break; 324 case ADBK_KEYDOWN(ADBK_DOWN): 325 result = 1; 326 break; 327 case ADBK_KEYUP(ADBK_DOWN): 328 result = 1; 329 pmf_event_inject(NULL, PMFE_DISPLAY_BRIGHTNESS_DOWN); 330 break; 331 case ADBK_KEYUP(ADBK_SHIFT): 332 case ADBK_KEYDOWN(ADBK_SHIFT): 333 case ADBK_KEYUP(ADBK_CONTROL): 334 case ADBK_KEYDOWN(ADBK_CONTROL): 335 case ADBK_KEYUP(ADBK_FLOWER): 336 case ADBK_KEYDOWN(ADBK_FLOWER): 337 /* ctrl, shift, cmd */ 338 aed_dokeyupdown(event); 339 break; 340 #if defined(EMULFKEYS) 341 case ADBK_KEYDOWN(ADBK_1): 342 if (!fkey) 343 fkey = ADBK_F1; 344 case ADBK_KEYDOWN(ADBK_2): 345 if (!fkey) 346 fkey = ADBK_F2; 347 case ADBK_KEYDOWN(ADBK_3): 348 if (!fkey) 349 fkey = ADBK_F3; 350 case ADBK_KEYDOWN(ADBK_4): 351 if (!fkey) 352 fkey = ADBK_F4; 353 case ADBK_KEYDOWN(ADBK_5): 354 if (!fkey) 355 fkey = ADBK_F5; 356 case ADBK_KEYDOWN(ADBK_6): 357 if (!fkey) 358 fkey = ADBK_F6; 359 case ADBK_KEYDOWN(ADBK_7): 360 if (!fkey) 361 fkey = ADBK_F7; 362 case ADBK_KEYDOWN(ADBK_8): 363 if (!fkey) 364 fkey = ADBK_F8; 365 366 result = 2; 367 /* key down */ 368 new_event = *event; 369 370 /* send FKEY-down */ 371 new_event.u.k.key = ADBK_KEYDOWN(fkey); 372 new_event.bytes[0] = new_event.u.k.key; 373 microtime(&new_event.timestamp); 374 aed_dokeyupdown(&new_event); 375 memcpy(event, &new_event, sizeof(new_event)); 376 break; 377 case ADBK_KEYUP(ADBK_1): 378 if (!fkey) 379 fkey = ADBK_F1; 380 case ADBK_KEYUP(ADBK_2): 381 if (!fkey) 382 fkey = ADBK_F2; 383 case ADBK_KEYUP(ADBK_3): 384 if (!fkey) 385 fkey = ADBK_F3; 386 case ADBK_KEYUP(ADBK_4): 387 if (!fkey) 388 fkey = ADBK_F4; 389 case ADBK_KEYUP(ADBK_5): 390 if (!fkey) 391 fkey = ADBK_F5; 392 case ADBK_KEYUP(ADBK_6): 393 if (!fkey) 394 fkey = ADBK_F6; 395 case ADBK_KEYUP(ADBK_7): 396 if (!fkey) 397 fkey = ADBK_F7; 398 case ADBK_KEYUP(ADBK_8): 399 if (!fkey) 400 fkey = ADBK_F8; 401 402 result = 2; 403 /* key up */ 404 new_event = *event; 405 406 /* send FKEY-up */ 407 new_event.u.k.key = ADBK_KEYUP(fkey); 408 new_event.bytes[0] = new_event.u.k.key; 409 microtime(&new_event.timestamp); 410 aed_dokeyupdown(&new_event); 411 memcpy(event, &new_event, sizeof(new_event)); 412 break; 413 #endif 414 default: 415 if (event->u.k.key & 0x80) 416 /* ignore keyup */ 417 break; 418 419 /* key down */ 420 new_event = *event; 421 422 /* send option-down */ 423 new_event.u.k.key = ADBK_KEYDOWN(ADBK_OPTION); 424 new_event.bytes[0] = new_event.u.k.key; 425 microtime(&new_event.timestamp); 426 aed_dokeyupdown(&new_event); 427 428 /* send key-down */ 429 new_event.u.k.key = event->bytes[0]; 430 new_event.bytes[0] = new_event.u.k.key; 431 microtime(&new_event.timestamp); 432 aed_dokeyupdown(&new_event); 433 434 /* send key-up */ 435 new_event.u.k.key = 436 ADBK_KEYUP(ADBK_KEYVAL(event->bytes[0])); 437 microtime(&new_event.timestamp); 438 new_event.bytes[0] = new_event.u.k.key; 439 aed_dokeyupdown(&new_event); 440 441 /* send option-up */ 442 new_event.u.k.key = ADBK_KEYUP(ADBK_OPTION); 443 new_event.bytes[0] = new_event.u.k.key; 444 microtime(&new_event.timestamp); 445 aed_dokeyupdown(&new_event); 446 break; 447 } 448 } else { 449 aed_dokeyupdown(event); 450 } 451 452 return result; 453 } 454 455 /* 456 * Keyboard autorepeat timeout function. Sends key up/down events 457 * for the repeating key and schedules the next call at sc_rptinterval 458 * ticks in the future. 459 */ 460 static void 461 aed_kbdrpt(void *kstate) 462 { 463 struct aed_softc *sc = (struct aed_softc *)kstate; 464 465 sc->sc_rptevent.bytes[0] |= 0x80; 466 microtime(&sc->sc_rptevent.timestamp); 467 aed_handoff(&sc->sc_rptevent); /* do key up */ 468 469 sc->sc_rptevent.bytes[0] &= 0x7f; 470 microtime(&sc->sc_rptevent.timestamp); 471 aed_handoff(&sc->sc_rptevent); /* do key down */ 472 473 if (sc->sc_repeating == sc->sc_rptevent.u.k.key) { 474 callout_reset(&sc->sc_repeat_ch, sc->sc_rptinterval, 475 aed_kbdrpt, kstate); 476 } 477 } 478 479 480 /* 481 * Cancels the currently repeating key event if there is one, schedules 482 * a new repeating key event if needed, and hands the event off to the 483 * appropriate subsystem. 484 */ 485 static void 486 aed_dokeyupdown(adb_event_t *event) 487 { 488 int kbd_key; 489 490 kbd_key = ADBK_KEYVAL(event->u.k.key); 491 if (ADBK_PRESS(event->u.k.key) && keyboard[kbd_key][0] != 0) { 492 /* ignore shift & control */ 493 if (aed_sc->sc_repeating != -1) { 494 callout_stop(&aed_sc->sc_repeat_ch); 495 } 496 aed_sc->sc_rptevent = *event; 497 aed_sc->sc_repeating = kbd_key; 498 callout_reset(&aed_sc->sc_repeat_ch, aed_sc->sc_rptdelay, 499 aed_kbdrpt, (void *)aed_sc); 500 } else { 501 if (aed_sc->sc_repeating != -1) { 502 aed_sc->sc_repeating = -1; 503 callout_stop(&aed_sc->sc_repeat_ch); 504 } 505 aed_sc->sc_rptevent = *event; 506 } 507 aed_handoff(event); 508 } 509 510 /* 511 * Place the event in the event queue if a requesting device is open 512 * and we are not polling, otherwise, pass it up to the console driver. 513 */ 514 static void 515 aed_handoff(adb_event_t *event) 516 { 517 if (aed_sc->sc_open && !adb_polling) 518 aed_enqevent(event); 519 } 520 521 /* 522 * Place the event in the event queue and wakeup any waiting processes. 523 */ 524 static void 525 aed_enqevent(adb_event_t *event) 526 { 527 int s; 528 529 s = splvm(); 530 531 #ifdef DIAGNOSTIC 532 if (aed_sc->sc_evq_tail < 0 || aed_sc->sc_evq_tail >= AED_MAX_EVENTS) 533 panic("adb: event queue tail is out of bounds"); 534 535 if (aed_sc->sc_evq_len < 0 || aed_sc->sc_evq_len > AED_MAX_EVENTS) 536 panic("adb: event queue len is out of bounds"); 537 #endif 538 539 if (aed_sc->sc_evq_len == AED_MAX_EVENTS) { 540 splx(s); 541 return; /* Oh, well... */ 542 } 543 aed_sc->sc_evq[(aed_sc->sc_evq_len + aed_sc->sc_evq_tail) % 544 AED_MAX_EVENTS] = *event; 545 aed_sc->sc_evq_len++; 546 547 selnotify(&aed_sc->sc_selinfo, 0, 0); 548 if (aed_sc->sc_ioproc) 549 psignal(aed_sc->sc_ioproc, SIGIO); 550 551 splx(s); 552 } 553 554 int 555 aedopen(dev_t dev, int flag, int mode, struct lwp *l) 556 { 557 struct aed_softc *sc; 558 int s; 559 560 sc = device_lookup_private(&aed_cd, minor(dev)); 561 if (sc == NULL) 562 return (ENXIO); 563 564 s = splvm(); 565 if (sc->sc_open) { 566 splx(s); 567 return (EBUSY); 568 } 569 aed_sc->sc_evq_tail = 0; 570 aed_sc->sc_evq_len = 0; 571 aed_sc->sc_open = 1; 572 aed_sc->sc_ioproc = l->l_proc; 573 splx(s); 574 575 return 0; 576 } 577 578 579 int 580 aedclose(dev_t dev, int flag, int mode, struct lwp *l) 581 { 582 int s; 583 584 s = splvm(); 585 aed_sc->sc_open = 0; 586 aed_sc->sc_ioproc = NULL; 587 splx(s); 588 589 return (0); 590 } 591 592 593 int 594 aedread(dev_t dev, struct uio *uio, int flag) 595 { 596 int s, error; 597 int willfit; 598 int total; 599 int firstmove; 600 int moremove; 601 602 if (uio->uio_resid < sizeof(adb_event_t)) 603 return (EMSGSIZE); /* close enough. */ 604 605 s = splvm(); 606 if (aed_sc->sc_evq_len == 0) { 607 splx(s); 608 return (0); 609 } 610 willfit = howmany(uio->uio_resid, sizeof(adb_event_t)); 611 total = (aed_sc->sc_evq_len < willfit) ? aed_sc->sc_evq_len : willfit; 612 613 firstmove = (aed_sc->sc_evq_tail + total > AED_MAX_EVENTS) 614 ? (AED_MAX_EVENTS - aed_sc->sc_evq_tail) : total; 615 616 error = uiomove((void *) & aed_sc->sc_evq[aed_sc->sc_evq_tail], 617 firstmove * sizeof(adb_event_t), uio); 618 if (error) { 619 splx(s); 620 return (error); 621 } 622 moremove = total - firstmove; 623 624 if (moremove > 0) { 625 error = uiomove((void *) & aed_sc->sc_evq[0], 626 moremove * sizeof(adb_event_t), uio); 627 if (error) { 628 splx(s); 629 return (error); 630 } 631 } 632 aed_sc->sc_evq_tail = (aed_sc->sc_evq_tail + total) % AED_MAX_EVENTS; 633 aed_sc->sc_evq_len -= total; 634 splx(s); 635 return (0); 636 } 637 638 int 639 aedioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 640 { 641 switch (cmd) { 642 case ADBIOC_DEVSINFO: { 643 adb_devinfo_t *di; 644 ADBDataBlock adbdata; 645 int totaldevs; 646 int adbaddr; 647 int i; 648 649 di = (void *)data; 650 651 /* Initialize to no devices */ 652 for (i = 0; i < 16; i++) 653 di->dev[i].addr = -1; 654 655 totaldevs = CountADBs(); 656 for (i = 1; i <= totaldevs; i++) { 657 adbaddr = GetIndADB(&adbdata, i); 658 di->dev[adbaddr].addr = adbaddr; 659 di->dev[adbaddr].default_addr = (int)(adbdata.origADBAddr); 660 di->dev[adbaddr].handler_id = (int)(adbdata.devType); 661 } 662 663 /* Must call ADB Manager to get devices now */ 664 break; 665 } 666 667 case ADBIOC_GETREPEAT:{ 668 adb_rptinfo_t *ri; 669 670 ri = (void *)data; 671 ri->delay_ticks = aed_sc->sc_rptdelay; 672 ri->interval_ticks = aed_sc->sc_rptinterval; 673 break; 674 } 675 676 case ADBIOC_SETREPEAT:{ 677 adb_rptinfo_t *ri; 678 679 ri = (void *) data; 680 aed_sc->sc_rptdelay = ri->delay_ticks; 681 aed_sc->sc_rptinterval = ri->interval_ticks; 682 break; 683 } 684 685 case ADBIOC_RESET: 686 /* Do nothing for now */ 687 break; 688 689 case ADBIOC_LISTENCMD: 690 /* adb_listencmd_t *lc = data; */ 691 692 default: 693 return (EINVAL); 694 } 695 return (0); 696 } 697 698 699 int 700 aedpoll(dev_t dev, int events, struct lwp *l) 701 { 702 int s, revents; 703 704 revents = events & (POLLOUT | POLLWRNORM); 705 706 if ((events & (POLLIN | POLLRDNORM)) == 0) 707 return (revents); 708 709 s = splvm(); 710 if (aed_sc->sc_evq_len > 0) 711 revents |= events & (POLLIN | POLLRDNORM); 712 else 713 selrecord(l, &aed_sc->sc_selinfo); 714 splx(s); 715 716 return (revents); 717 } 718 719 static void 720 filt_aedrdetach(struct knote *kn) 721 { 722 int s; 723 724 s = splvm(); 725 selremove_knote(&aed_sc->sc_selinfo, kn); 726 splx(s); 727 } 728 729 static int 730 filt_aedread(struct knote *kn, long hint) 731 { 732 733 kn->kn_data = aed_sc->sc_evq_len * sizeof(adb_event_t); 734 return (kn->kn_data > 0); 735 } 736 737 static const struct filterops aedread_filtops = { 738 .f_flags = FILTEROP_ISFD, 739 .f_attach = NULL, 740 .f_detach = filt_aedrdetach, 741 .f_event = filt_aedread, 742 }; 743 744 int 745 aedkqfilter(dev_t dev, struct knote *kn) 746 { 747 int s; 748 749 switch (kn->kn_filter) { 750 case EVFILT_READ: 751 kn->kn_fop = &aedread_filtops; 752 s = splvm(); 753 selrecord_knote(&aed_sc->sc_selinfo, kn); 754 splx(s); 755 break; 756 757 case EVFILT_WRITE: 758 kn->kn_fop = &seltrue_filtops; 759 break; 760 761 default: 762 return (EINVAL); 763 } 764 765 return (0); 766 } 767 768 static void 769 aed_brightness_down(device_t dev) 770 { 771 int level, step; 772 773 level = brightness; 774 if (level <= 4) /* logarithmic brightness curve. */ 775 step = 1; 776 else 777 step = BRIGHTNESS_STEP; 778 779 level = uimax(BRIGHTNESS_MIN, level - step); 780 brightness = pm_set_brightness(level); 781 } 782 783 static void 784 aed_brightness_up(device_t dev) 785 { 786 int level, step; 787 788 level = brightness; 789 if (level <= 4) /* logarithmic brightness curve. */ 790 step = 1; 791 else 792 step = BRIGHTNESS_STEP; 793 794 level = uimin(BRIGHTNESS_MAX, level + step); 795 brightness = pm_set_brightness(level); 796 } 797 798 static void 799 aed_display_on(device_t dev) 800 { 801 (void)pm_set_brightness(brightness); 802 } 803 804 static void 805 aed_display_off(device_t dev) 806 { 807 (void)pm_set_brightness(0); 808 } 809