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