The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/uart/uart_kbd_sun.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 68a0aa05fa173a0eefa93edfc2781b76


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.