1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2003 Jake Burkholder. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include "opt_compat.h" 33 #include "opt_kbd.h" 34 #include "opt_sunkbd.h" 35 36 #if (defined(SUNKBD_EMULATE_ATKBD) && defined(SUNKBD_DFLT_KEYMAP)) || \ 37 !defined(SUNKBD_EMULATE_ATKBD) 38 #define KBD_DFLT_KEYMAP 39 #endif 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/bus.h> 44 #include <sys/interrupt.h> 45 #include <sys/kbio.h> 46 #include <sys/kernel.h> 47 #include <sys/limits.h> 48 49 #include <machine/bus.h> 50 51 #include <dev/kbd/kbdreg.h> 52 #include <dev/kbd/kbdtables.h> 53 54 #include <dev/uart/uart.h> 55 #include <dev/uart/uart_bus.h> 56 #include <dev/uart/uart_cpu.h> 57 58 #include <dev/uart/uart_kbd_sun.h> 59 #if !defined(SUNKBD_EMULATE_ATKBD) 60 #include <dev/uart/uart_kbd_sun_tables.h> 61 #endif 62 63 #if defined(SUNKBD_EMULATE_ATKBD) && defined(SUNKBD_DFLT_KEYMAP) 64 #include "sunkbdmap.h" 65 #endif 66 #include "uart_if.h" 67 68 #define SUNKBD_DRIVER_NAME "sunkbd" 69 70 #define TODO printf("%s: unimplemented", __func__) 71 72 struct sunkbd_softc { 73 keyboard_t sc_kbd; 74 struct uart_softc *sc_uart; 75 struct uart_devinfo *sc_sysdev; 76 77 struct callout sc_repeat_callout; 78 int sc_repeat_key; 79 80 int sc_accents; 81 int sc_composed_char; 82 int sc_flags; 83 #define KPCOMPOSE (1 << 0) 84 int sc_mode; 85 int sc_polling; 86 int sc_repeating; 87 int sc_state; 88 89 #if defined(SUNKBD_EMULATE_ATKBD) 90 int sc_buffered_char[2]; 91 #endif 92 }; 93 94 static int sunkbd_configure(int flags); 95 static int sunkbd_probe_keyboard(struct uart_devinfo *di); 96 97 static int sunkbd_probe(int unit, void *arg, int flags); 98 static int sunkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags); 99 static int sunkbd_term(keyboard_t *kbd); 100 static int sunkbd_intr(keyboard_t *kbd, void *arg); 101 static int sunkbd_test_if(keyboard_t *kbd); 102 static int sunkbd_enable(keyboard_t *kbd); 103 static int sunkbd_disable(keyboard_t *kbd); 104 static int sunkbd_read(keyboard_t *kbd, int wait); 105 static int sunkbd_check(keyboard_t *kbd); 106 static u_int sunkbd_read_char(keyboard_t *kbd, int wait); 107 static int sunkbd_check_char(keyboard_t *kbd); 108 static int sunkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data); 109 static int sunkbd_lock(keyboard_t *kbd, int lock); 110 static void sunkbd_clear_state(keyboard_t *kbd); 111 static int sunkbd_get_state(keyboard_t *kbd, void *buf, size_t len); 112 static int sunkbd_set_state(keyboard_t *kbd, void *buf, size_t len); 113 static int sunkbd_poll_mode(keyboard_t *kbd, int on); 114 static void sunkbd_diag(keyboard_t *kbd, int level); 115 116 static void sunkbd_repeat(void *v); 117 #if defined(SUNKBD_EMULATE_ATKBD) 118 static int keycode2scancode(int keycode, int shift, int up); 119 #endif 120 121 static keyboard_switch_t sunkbdsw = { 122 sunkbd_probe, 123 sunkbd_init, 124 sunkbd_term, 125 sunkbd_intr, 126 sunkbd_test_if, 127 sunkbd_enable, 128 sunkbd_disable, 129 sunkbd_read, 130 sunkbd_check, 131 sunkbd_read_char, 132 sunkbd_check_char, 133 sunkbd_ioctl, 134 sunkbd_lock, 135 sunkbd_clear_state, 136 sunkbd_get_state, 137 sunkbd_set_state, 138 genkbd_get_fkeystr, 139 sunkbd_poll_mode, 140 sunkbd_diag 141 }; 142 143 KEYBOARD_DRIVER(sunkbd, sunkbdsw, sunkbd_configure); 144 145 static struct sunkbd_softc sunkbd_softc; 146 static struct uart_devinfo uart_keyboard; 147 148 #if defined(SUNKBD_EMULATE_ATKBD) 149 150 #define SCAN_PRESS 0x000 151 #define SCAN_RELEASE 0x080 152 #define SCAN_PREFIX_E0 0x100 153 #define SCAN_PREFIX_E1 0x200 154 #define SCAN_PREFIX_CTL 0x400 155 #define SCAN_PREFIX_SHIFT 0x800 156 #define SCAN_PREFIX (SCAN_PREFIX_E0 | SCAN_PREFIX_E1 | \ 157 SCAN_PREFIX_CTL | SCAN_PREFIX_SHIFT) 158 159 #define NOTR 0x0 /* no translation */ 160 161 static const uint8_t sunkbd_trtab[] = { 162 NOTR, 0x6d, 0x78, 0x6e, 0x79, 0x3b, 0x3c, 0x44, /* 0x00 - 0x07 */ 163 0x3d, 0x57, 0x3e, 0x58, 0x3f, 0x5d, 0x40, NOTR, /* 0x08 - 0x0f */ 164 0x41, 0x42, 0x43, 0x38, 0x5f, 0x68, 0x5c, 0x46, /* 0x10 - 0x17 */ 165 0x61, 0x6f, 0x70, 0x64, 0x62, 0x01, 0x02, 0x03, /* 0x18 - 0x1f */ 166 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, /* 0x20 - 0x27 */ 167 0x0c, 0x0d, 0x29, 0x0e, 0x66, 0x77, 0x5b, 0x37, /* 0x28 - 0x2f */ 168 0x7a, 0x71, 0x53, 0x74, 0x5e, 0x0f, 0x10, 0x11, /* 0x30 - 0x37 */ 169 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, /* 0x38 - 0x3f */ 170 0x1a, 0x1b, 0x67, 0x6b, 0x47, 0x48, 0x49, 0x4a, /* 0x40 - 0x47 */ 171 0x73, 0x72, 0x63, NOTR, 0x1d, 0x1e, 0x1f, 0x20, /* 0x48 - 0x4f */ 172 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, /* 0x50 - 0x57 */ 173 0x2b, 0x1c, 0x59, 0x4b, 0x4c, 0x4d, 0x52, 0x75, /* 0x58 - 0x5f */ 174 0x60, 0x76, 0x45, 0x2a, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x60 - 0x67 */ 175 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, NOTR, /* 0x68 - 0x6f */ 176 0x4f, 0x50, 0x51, NOTR, NOTR, NOTR, 0x6c, 0x3a, /* 0x70 - 0x77 */ 177 0x69, 0x39, 0x6a, 0x65, 0x56, 0x4e, NOTR, NOTR /* 0x78 - 0x7f */ 178 }; 179 180 #endif 181 182 static int 183 sunkbd_probe_keyboard(struct uart_devinfo *di) 184 { 185 int c, id, ltries, tries; 186 187 for (tries = 5; tries != 0; tries--) { 188 uart_putc(di, SKBD_CMD_RESET); 189 for (ltries = 1000; ltries != 0; ltries--) { 190 if (uart_poll(di) == SKBD_RSP_RESET) 191 break; 192 DELAY(1000); 193 } 194 if (ltries == 0) 195 continue; 196 id = -1; 197 for (ltries = 1000; ltries != 0; ltries--) { 198 switch (c = uart_poll(di)) { 199 case -1: 200 break; 201 case SKBD_RSP_IDLE: 202 return (id); 203 default: 204 id = c; 205 } 206 DELAY(1000); 207 } 208 } 209 return (-1); 210 } 211 212 static int sunkbd_attach(struct uart_softc *sc); 213 static void sunkbd_uart_intr(void *arg); 214 215 static int 216 sunkbd_configure(int flags) 217 { 218 struct sunkbd_softc *sc; 219 220 /* 221 * We are only prepared to be used for the high-level console 222 * when the keyboard is both configured and attached. 223 */ 224 if (!(flags & KB_CONF_PROBE_ONLY)) { 225 if (KBD_IS_INITIALIZED(&sunkbd_softc.sc_kbd)) 226 goto found; 227 else 228 return (0); 229 } 230 231 if (uart_cpu_getdev(UART_DEV_KEYBOARD, &uart_keyboard)) 232 return (0); 233 if (uart_probe(&uart_keyboard)) 234 return (0); 235 uart_init(&uart_keyboard); 236 237 uart_keyboard.type = UART_DEV_KEYBOARD; 238 uart_keyboard.attach = sunkbd_attach; 239 uart_add_sysdev(&uart_keyboard); 240 241 if (sunkbd_probe_keyboard(&uart_keyboard) != KB_SUN4) 242 return (0); 243 244 sc = &sunkbd_softc; 245 callout_init(&sc->sc_repeat_callout, 0); 246 sunkbd_clear_state(&sc->sc_kbd); 247 248 #if defined(SUNKBD_EMULATE_ATKBD) 249 kbd_init_struct(&sc->sc_kbd, SUNKBD_DRIVER_NAME, KB_101, 0, 0, 0, 0); 250 kbd_set_maps(&sc->sc_kbd, &key_map, &accent_map, fkey_tab, 251 sizeof(fkey_tab) / sizeof(fkey_tab[0])); 252 #else 253 kbd_init_struct(&sc->sc_kbd, SUNKBD_DRIVER_NAME, KB_OTHER, 0, 0, 0, 0); 254 kbd_set_maps(&sc->sc_kbd, &keymap_sun_us_unix_kbd, 255 &accentmap_sun_us_unix_kbd, fkey_tab, 256 sizeof(fkey_tab) / sizeof(fkey_tab[0])); 257 #endif 258 sc->sc_mode = K_XLATE; 259 kbd_register(&sc->sc_kbd); 260 261 sc->sc_sysdev = &uart_keyboard; 262 263 found: 264 /* Return number of found keyboards. */ 265 return (1); 266 } 267 268 static int 269 sunkbd_attach(struct uart_softc *sc) 270 { 271 272 /* 273 * Don't attach if we didn't probe the keyboard. Note that 274 * the UART is still marked as a system device in that case. 275 */ 276 if (sunkbd_softc.sc_sysdev == NULL) { 277 device_printf(sc->sc_dev, "keyboard not present\n"); 278 return (0); 279 } 280 281 if (sc->sc_sysdev != NULL) { 282 sunkbd_softc.sc_uart = sc; 283 284 #ifdef KBD_INSTALL_CDEV 285 kbd_attach(&sunkbd_softc.sc_kbd); 286 #endif 287 sunkbd_enable(&sunkbd_softc.sc_kbd); 288 289 swi_add(&tty_intr_event, uart_driver_name, sunkbd_uart_intr, 290 &sunkbd_softc, SWI_TTY, INTR_TYPE_TTY, &sc->sc_softih); 291 292 sc->sc_opened = 1; 293 KBD_INIT_DONE(&sunkbd_softc.sc_kbd); 294 } 295 296 return (0); 297 } 298 299 static void 300 sunkbd_uart_intr(void *arg) 301 { 302 struct sunkbd_softc *sc = arg; 303 int pend; 304 305 if (sc->sc_uart->sc_leaving) 306 return; 307 308 pend = atomic_readandclear_32(&sc->sc_uart->sc_ttypend); 309 if (!(pend & SER_INT_MASK)) 310 return; 311 312 if (pend & SER_INT_RXREADY) { 313 if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) { 314 sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd, 315 KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg); 316 } 317 } 318 } 319 320 static int 321 sunkbd_probe(int unit, void *arg, int flags) 322 { 323 324 TODO; 325 return (0); 326 } 327 328 static int 329 sunkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) 330 { 331 332 TODO; 333 return (0); 334 } 335 336 static int 337 sunkbd_term(keyboard_t *kbd) 338 { 339 340 TODO; 341 return (0); 342 } 343 344 static int 345 sunkbd_intr(keyboard_t *kbd, void *arg) 346 { 347 348 TODO; 349 return (0); 350 } 351 352 static int 353 sunkbd_test_if(keyboard_t *kbd) 354 { 355 356 TODO; 357 return (0); 358 } 359 360 static int 361 sunkbd_enable(keyboard_t *kbd) 362 { 363 364 KBD_ACTIVATE(kbd); 365 return (0); 366 } 367 368 static int 369 sunkbd_disable(keyboard_t *kbd) 370 { 371 372 KBD_DEACTIVATE(kbd); 373 return (0); 374 } 375 376 static int 377 sunkbd_read(keyboard_t *kbd, int wait) 378 { 379 380 TODO; 381 return (0); 382 } 383 384 static int 385 sunkbd_check(keyboard_t *kbd) 386 { 387 struct sunkbd_softc *sc; 388 389 if (!KBD_IS_ACTIVE(kbd)) 390 return (FALSE); 391 392 sc = (struct sunkbd_softc *)kbd; 393 394 #if defined(SUNKBD_EMULATE_ATKBD) 395 if (sc->sc_buffered_char[0]) 396 return (TRUE); 397 #endif 398 399 if (sc->sc_repeating) 400 return (TRUE); 401 402 if (sc->sc_uart != NULL && !uart_rx_empty(sc->sc_uart)) 403 return (TRUE); 404 405 if (sc->sc_polling != 0 && sc->sc_sysdev != NULL && 406 uart_rxready(sc->sc_sysdev)) 407 return (TRUE); 408 409 return (FALSE); 410 } 411 412 static u_int 413 sunkbd_read_char(keyboard_t *kbd, int wait) 414 { 415 struct sunkbd_softc *sc; 416 int key, release, repeated, suncode; 417 418 sc = (struct sunkbd_softc *)kbd; 419 420 #if defined(SUNKBD_EMULATE_ATKBD) 421 if (sc->sc_mode == K_RAW && sc->sc_buffered_char[0]) { 422 key = sc->sc_buffered_char[0]; 423 if (key & SCAN_PREFIX) { 424 sc->sc_buffered_char[0] = key & ~SCAN_PREFIX; 425 return ((key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1); 426 } else { 427 sc->sc_buffered_char[0] = sc->sc_buffered_char[1]; 428 sc->sc_buffered_char[1] = 0; 429 return (key); 430 } 431 } 432 #endif 433 434 repeated = 0; 435 if (sc->sc_repeating) { 436 repeated = 1; 437 sc->sc_repeating = 0; 438 callout_reset(&sc->sc_repeat_callout, hz / 10, 439 sunkbd_repeat, sc); 440 suncode = sc->sc_repeat_key; 441 goto process_code; 442 } 443 444 for (;;) { 445 next_code: 446 if (!(sc->sc_flags & KPCOMPOSE) && (sc->sc_composed_char > 0)) { 447 key = sc->sc_composed_char; 448 sc->sc_composed_char = 0; 449 if (key > UCHAR_MAX) 450 return (ERRKEY); 451 return (key); 452 } 453 454 if (sc->sc_uart != NULL && !uart_rx_empty(sc->sc_uart)) { 455 suncode = uart_rx_get(sc->sc_uart); 456 } else if (sc->sc_polling != 0 && sc->sc_sysdev != NULL) { 457 if (wait) 458 suncode = uart_getc(sc->sc_sysdev); 459 else if ((suncode = uart_poll(sc->sc_sysdev)) == -1) 460 return (NOKEY); 461 } else { 462 return (NOKEY); 463 } 464 465 switch (suncode) { 466 case SKBD_RSP_IDLE: 467 break; 468 default: 469 process_code: 470 ++kbd->kb_count; 471 key = SKBD_KEY_CHAR(suncode); 472 release = suncode & SKBD_KEY_RELEASE; 473 if (!repeated) { 474 if (release == 0) { 475 callout_reset(&sc->sc_repeat_callout, 476 hz / 2, sunkbd_repeat, sc); 477 sc->sc_repeat_key = suncode; 478 } else if (sc->sc_repeat_key == key) { 479 callout_stop(&sc->sc_repeat_callout); 480 sc->sc_repeat_key = -1; 481 } 482 } 483 484 #if defined(SUNKBD_EMULATE_ATKBD) 485 key = sunkbd_trtab[key]; 486 if (key == NOTR) 487 return (NOKEY); 488 489 if (!repeated) { 490 switch (key) { 491 case 0x1d: /* ctrl */ 492 if (release != 0) 493 sc->sc_flags &= ~CTLS; 494 else 495 sc->sc_flags |= CTLS; 496 break; 497 case 0x2a: /* left shift */ 498 case 0x36: /* right shift */ 499 if (release != 0) 500 sc->sc_flags &= ~SHIFTS; 501 else 502 sc->sc_flags |= SHIFTS; 503 break; 504 case 0x38: /* alt */ 505 case 0x5d: /* altgr */ 506 if (release != 0) 507 sc->sc_flags &= ~ALTS; 508 else 509 sc->sc_flags |= ALTS; 510 break; 511 } 512 } 513 if (sc->sc_mode == K_RAW) { 514 key = keycode2scancode(key, sc->sc_flags, 515 release); 516 if (key & SCAN_PREFIX) { 517 if (key & SCAN_PREFIX_CTL) { 518 sc->sc_buffered_char[0] = 519 0x1d | (key & SCAN_RELEASE); 520 sc->sc_buffered_char[1] = 521 key & ~SCAN_PREFIX; 522 } else if (key & SCAN_PREFIX_SHIFT) { 523 sc->sc_buffered_char[0] = 524 0x2a | (key & SCAN_RELEASE); 525 sc->sc_buffered_char[1] = 526 key & ~SCAN_PREFIX_SHIFT; 527 } else { 528 sc->sc_buffered_char[0] = 529 key & ~SCAN_PREFIX; 530 sc->sc_buffered_char[1] = 0; 531 } 532 return ((key & SCAN_PREFIX_E0) ? 533 0xe0 : 0xe1); 534 } 535 return (key); 536 } 537 switch (key) { 538 case 0x5c: /* print screen */ 539 if (sc->sc_flags & ALTS) 540 key = 0x54; /* sysrq */ 541 break; 542 case 0x68: /* pause/break */ 543 if (sc->sc_flags & CTLS) 544 key = 0x6c; /* break */ 545 break; 546 } 547 548 if (sc->sc_mode == K_CODE) 549 return (key | release); 550 #else 551 if (sc->sc_mode == K_RAW || sc->sc_mode == K_CODE) 552 return (suncode); 553 #endif 554 555 #if defined(SUNKBD_EMULATE_ATKBD) 556 if (key == 0x38) { /* left alt (KP compose key) */ 557 #else 558 if (key == 0x13) { /* left alt (KP compose key) */ 559 #endif 560 if (release != 0) { 561 if (sc->sc_flags & KPCOMPOSE) { 562 sc->sc_flags &= ~KPCOMPOSE; 563 if (sc->sc_composed_char > 564 UCHAR_MAX) 565 sc->sc_composed_char = 566 0; 567 } 568 } else { 569 if (!(sc->sc_flags & KPCOMPOSE)) { 570 sc->sc_flags |= KPCOMPOSE; 571 sc->sc_composed_char = 0; 572 } 573 } 574 } 575 if (sc->sc_flags & KPCOMPOSE) { 576 switch (suncode) { 577 case 0x44: /* KP 7 */ 578 case 0x45: /* KP 8 */ 579 case 0x46: /* KP 9 */ 580 sc->sc_composed_char *= 10; 581 sc->sc_composed_char += suncode - 0x3d; 582 if (sc->sc_composed_char > UCHAR_MAX) 583 return (ERRKEY); 584 goto next_code; 585 case 0x5b: /* KP 4 */ 586 case 0x5c: /* KP 5 */ 587 case 0x5d: /* KP 6 */ 588 sc->sc_composed_char *= 10; 589 sc->sc_composed_char += suncode - 0x58; 590 if (sc->sc_composed_char > UCHAR_MAX) 591 return (ERRKEY); 592 goto next_code; 593 case 0x70: /* KP 1 */ 594 case 0x71: /* KP 2 */ 595 case 0x72: /* KP 3 */ 596 sc->sc_composed_char *= 10; 597 sc->sc_composed_char += suncode - 0x6f; 598 if (sc->sc_composed_char > UCHAR_MAX) 599 return (ERRKEY); 600 goto next_code; 601 case 0x5e: /* KP 0 */ 602 sc->sc_composed_char *= 10; 603 if (sc->sc_composed_char > UCHAR_MAX) 604 return (ERRKEY); 605 goto next_code; 606 607 case 0x44 | SKBD_KEY_RELEASE: /* KP 7 */ 608 case 0x45 | SKBD_KEY_RELEASE: /* KP 8 */ 609 case 0x46 | SKBD_KEY_RELEASE: /* KP 9 */ 610 case 0x5b | SKBD_KEY_RELEASE: /* KP 4 */ 611 case 0x5c | SKBD_KEY_RELEASE: /* KP 5 */ 612 case 0x5d | SKBD_KEY_RELEASE: /* KP 6 */ 613 case 0x70 | SKBD_KEY_RELEASE: /* KP 1 */ 614 case 0x71 | SKBD_KEY_RELEASE: /* KP 2 */ 615 case 0x72 | SKBD_KEY_RELEASE: /* KP 3 */ 616 case 0x5e | SKBD_KEY_RELEASE: /* KP 0 */ 617 goto next_code; 618 default: 619 if (sc->sc_composed_char > 0) { 620 sc->sc_flags &= ~KPCOMPOSE; 621 sc->sc_composed_char = 0; 622 return (ERRKEY); 623 } 624 } 625 } 626 627 key = genkbd_keyaction(kbd, key, release, 628 &sc->sc_state, &sc->sc_accents); 629 if (key != NOKEY || repeated) 630 return (key); 631 } 632 } 633 return (0); 634 } 635 636 static int 637 sunkbd_check_char(keyboard_t *kbd) 638 { 639 struct sunkbd_softc *sc; 640 641 if (!KBD_IS_ACTIVE(kbd)) 642 return (FALSE); 643 644 sc = (struct sunkbd_softc *)kbd; 645 if (!(sc->sc_flags & KPCOMPOSE) && (sc->sc_composed_char > 0)) 646 return (TRUE); 647 648 return (sunkbd_check(kbd)); 649 } 650 651 static int 652 sunkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data) 653 { 654 struct sunkbd_softc *sc; 655 int c, error; 656 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) 657 int ival; 658 #endif 659 660 sc = (struct sunkbd_softc *)kbd; 661 error = 0; 662 switch (cmd) { 663 case KDGKBMODE: 664 *(int *)data = sc->sc_mode; 665 break; 666 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) 667 case _IO('K', 7): 668 ival = IOCPARM_IVAL(data); 669 data = (caddr_t)&ival; 670 /* FALLTHROUGH */ 671 #endif 672 case KDSKBMODE: 673 switch (*(int *)data) { 674 case K_XLATE: 675 if (sc->sc_mode != K_XLATE) { 676 /* make lock key state and LED state match */ 677 sc->sc_state &= ~LOCK_MASK; 678 sc->sc_state |= KBD_LED_VAL(kbd); 679 } 680 /* FALLTHROUGH */ 681 case K_RAW: 682 case K_CODE: 683 if (sc->sc_mode != *(int *)data) { 684 sunkbd_clear_state(kbd); 685 sc->sc_mode = *(int *)data; 686 } 687 break; 688 default: 689 error = EINVAL; 690 break; 691 } 692 break; 693 case KDGETLED: 694 *(int *)data = KBD_LED_VAL(kbd); 695 break; 696 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) 697 case _IO('K', 66): 698 ival = IOCPARM_IVAL(data); 699 data = (caddr_t)&ival; 700 /* FALLTHROUGH */ 701 #endif 702 case KDSETLED: 703 if (*(int *)data & ~LOCK_MASK) { 704 error = EINVAL; 705 break; 706 } 707 if (sc->sc_sysdev == NULL) 708 break; 709 c = 0; 710 if (*(int *)data & CLKED) 711 c |= SKBD_LED_CAPSLOCK; 712 if (*(int *)data & NLKED) 713 c |= SKBD_LED_NUMLOCK; 714 if (*(int *)data & SLKED) 715 c |= SKBD_LED_SCROLLLOCK; 716 uart_lock(sc->sc_sysdev->hwmtx); 717 sc->sc_sysdev->ops->putc(&sc->sc_sysdev->bas, SKBD_CMD_SETLED); 718 sc->sc_sysdev->ops->putc(&sc->sc_sysdev->bas, c); 719 uart_unlock(sc->sc_sysdev->hwmtx); 720 KBD_LED_VAL(kbd) = *(int *)data; 721 break; 722 case KDGKBSTATE: 723 *(int *)data = sc->sc_state & LOCK_MASK; 724 break; 725 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) 726 case _IO('K', 20): 727 ival = IOCPARM_IVAL(data); 728 data = (caddr_t)&ival; 729 /* FALLTHROUGH */ 730 #endif 731 case KDSKBSTATE: 732 if (*(int *)data & ~LOCK_MASK) { 733 error = EINVAL; 734 break; 735 } 736 sc->sc_state &= ~LOCK_MASK; 737 sc->sc_state |= *(int *)data; 738 /* set LEDs and quit */ 739 return (sunkbd_ioctl(kbd, KDSETLED, data)); 740 case KDSETREPEAT: 741 case KDSETRAD: 742 break; 743 case PIO_KEYMAP: 744 case OPIO_KEYMAP: 745 case PIO_KEYMAPENT: 746 case PIO_DEADKEYMAP: 747 default: 748 return (genkbd_commonioctl(kbd, cmd, data)); 749 } 750 return (error); 751 } 752 753 static int 754 sunkbd_lock(keyboard_t *kbd, int lock) 755 { 756 757 TODO; 758 return (0); 759 } 760 761 static void 762 sunkbd_clear_state(keyboard_t *kbd) 763 { 764 struct sunkbd_softc *sc; 765 766 sc = (struct sunkbd_softc *)kbd; 767 sc->sc_repeat_key = -1; 768 sc->sc_accents = 0; 769 sc->sc_composed_char = 0; 770 sc->sc_flags = 0; 771 sc->sc_polling = 0; 772 sc->sc_repeating = 0; 773 sc->sc_state &= LOCK_MASK; /* Preserve locking key state. */ 774 775 #if defined(SUNKBD_EMULATE_ATKBD) 776 sc->sc_buffered_char[0] = 0; 777 sc->sc_buffered_char[1] = 0; 778 #endif 779 } 780 781 static int 782 sunkbd_get_state(keyboard_t *kbd, void *buf, size_t len) 783 { 784 785 TODO; 786 return (0); 787 } 788 789 static int 790 sunkbd_set_state(keyboard_t *kbd, void *buf, size_t len) 791 { 792 793 TODO; 794 return (0); 795 } 796 797 static int 798 sunkbd_poll_mode(keyboard_t *kbd, int on) 799 { 800 struct sunkbd_softc *sc; 801 802 sc = (struct sunkbd_softc *)kbd; 803 if (on) 804 sc->sc_polling++; 805 else 806 sc->sc_polling--; 807 return (0); 808 } 809 810 static void 811 sunkbd_diag(keyboard_t *kbd, int level) 812 { 813 814 TODO; 815 } 816 817 static void 818 sunkbd_repeat(void *v) 819 { 820 struct sunkbd_softc *sc = v; 821 822 if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) { 823 if (sc->sc_repeat_key != -1) { 824 sc->sc_repeating = 1; 825 sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd, 826 KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg); 827 } 828 } 829 } 830 831 #if defined(SUNKBD_EMULATE_ATKBD) 832 static int 833 keycode2scancode(int keycode, int shift, int up) 834 { 835 static const int scan[] = { 836 /* KP enter, right ctrl, KP divide */ 837 0x1c , 0x1d , 0x35 , 838 /* print screen */ 839 0x37 | SCAN_PREFIX_SHIFT, 840 /* right alt, home, up, page up, left, right, end */ 841 0x38, 0x47, 0x48, 0x49, 0x4b, 0x4d, 0x4f, 842 /* down, page down, insert, delete */ 843 0x50, 0x51, 0x52, 0x53, 844 /* pause/break (see also below) */ 845 0x46, 846 /* 847 * MS: left window, right window, menu 848 * also Sun: left meta, right meta, compose 849 */ 850 0x5b, 0x5c, 0x5d, 851 /* Sun type 6 USB */ 852 /* help, stop, again, props, undo, front, copy */ 853 0x68, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 854 /* open, paste, find, cut, audiomute, audiolower, audioraise */ 855 0x64, 0x65, 0x66, 0x67, 0x25, 0x1f, 0x1e, 856 /* power */ 857 0x20 858 }; 859 int scancode; 860 861 scancode = keycode; 862 if ((keycode >= 89) && (keycode < 89 + nitems(scan))) 863 scancode = scan[keycode - 89] | SCAN_PREFIX_E0; 864 /* pause/break */ 865 if ((keycode == 104) && !(shift & CTLS)) 866 scancode = 0x45 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL; 867 if (shift & SHIFTS) 868 scancode &= ~SCAN_PREFIX_SHIFT; 869 return (scancode | (up ? SCAN_RELEASE : SCAN_PRESS)); 870 } 871 #endif 872