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/hyperv/input/hv_kbd.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) 2017 Microsoft Corp.
    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 unmodified, this list of conditions, and the following
   10  *    disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include "opt_evdev.h"
   31 
   32 #include <sys/param.h>
   33 #include <sys/kernel.h>
   34 #include <sys/conf.h>
   35 #include <sys/uio.h>
   36 #include <sys/bus.h>
   37 #include <sys/malloc.h>
   38 #include <sys/mbuf.h>
   39 #include <sys/module.h>
   40 #include <sys/limits.h>
   41 #include <sys/lock.h>
   42 #include <sys/taskqueue.h>
   43 #include <sys/selinfo.h>
   44 #include <sys/sysctl.h>
   45 #include <sys/poll.h>
   46 #include <sys/proc.h>
   47 #include <sys/queue.h>
   48 #include <sys/kthread.h>
   49 #include <sys/syscallsubr.h>
   50 #include <sys/sysproto.h>
   51 #include <sys/sema.h>
   52 #include <sys/signal.h>
   53 #include <sys/syslog.h>
   54 #include <sys/systm.h>
   55 #include <sys/mutex.h>
   56 #include <sys/callout.h>
   57 
   58 #include <sys/kbio.h>
   59 #include <dev/kbd/kbdreg.h>
   60 #include <dev/kbd/kbdtables.h>
   61 
   62 #ifdef EVDEV_SUPPORT
   63 #include <dev/evdev/evdev.h>
   64 #include <dev/evdev/input.h>
   65 #endif
   66 
   67 #include "dev/hyperv/input/hv_kbdc.h"
   68 
   69 #define HVKBD_MTX_LOCK(_m) do {         \
   70         mtx_lock(_m);                   \
   71 } while (0)
   72 
   73 #define HVKBD_MTX_UNLOCK(_m) do {       \
   74         mtx_unlock(_m);                 \
   75 } while (0)
   76 
   77 #define HVKBD_MTX_ASSERT(_m, _t) do {   \
   78         mtx_assert(_m, _t);             \
   79 } while (0)
   80 
   81 #define HVKBD_LOCK()            HVKBD_MTX_LOCK(&Giant)
   82 #define HVKBD_UNLOCK()          HVKBD_MTX_UNLOCK(&Giant)
   83 #define HVKBD_LOCK_ASSERT()     HVKBD_MTX_ASSERT(&Giant, MA_OWNED)
   84 
   85 #define HVKBD_FLAG_COMPOSE      0x00000001      /* compose char flag */
   86 #define HVKBD_FLAG_POLLING      0x00000002
   87 
   88 #ifdef EVDEV_SUPPORT
   89 static evdev_event_t hvkbd_ev_event;
   90 
   91 static const struct evdev_methods hvkbd_evdev_methods = {
   92         .ev_event = hvkbd_ev_event,
   93 };
   94 #endif
   95 
   96 /* early keyboard probe, not supported */
   97 static int
   98 hvkbd_configure(int flags)
   99 {
  100         return (0);
  101 }
  102 
  103 /* detect a keyboard, not used */
  104 static int
  105 hvkbd_probe(int unit, void *arg, int flags)
  106 {
  107         return (ENXIO);
  108 }
  109 
  110 /* reset and initialize the device, not used */
  111 static int
  112 hvkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
  113 {
  114         DEBUG_HVKBD(*kbdp, "%s\n", __func__);
  115         return (ENXIO);
  116 }
  117 
  118 /* test the interface to the device, not used */
  119 static int
  120 hvkbd_test_if(keyboard_t *kbd)
  121 {
  122         DEBUG_HVKBD(kbd, "%s\n", __func__);
  123         return (0);
  124 }
  125 
  126 /* finish using this keyboard, not used */
  127 static int
  128 hvkbd_term(keyboard_t *kbd)
  129 {
  130         DEBUG_HVKBD(kbd, "%s\n", __func__);
  131         return (ENXIO);
  132 }
  133 
  134 /* keyboard interrupt routine, not used */
  135 static int
  136 hvkbd_intr(keyboard_t *kbd, void *arg)
  137 {
  138         DEBUG_HVKBD(kbd, "%s\n", __func__);
  139         return (0);
  140 }
  141 
  142 /* lock the access to the keyboard, not used */
  143 static int
  144 hvkbd_lock(keyboard_t *kbd, int lock)
  145 {
  146         DEBUG_HVKBD(kbd, "%s\n", __func__);
  147         return (1);
  148 }
  149 
  150 /* save the internal state, not used */
  151 static int
  152 hvkbd_get_state(keyboard_t *kbd, void *buf, size_t len)
  153 {
  154         DEBUG_HVKBD(kbd,"%s\n",  __func__);
  155         return (len == 0) ? 1 : -1;
  156 }
  157 
  158 /* set the internal state, not used */
  159 static int
  160 hvkbd_set_state(keyboard_t *kbd, void *buf, size_t len)
  161 {
  162         DEBUG_HVKBD(kbd, "%s\n", __func__);
  163         return (EINVAL);
  164 }
  165 
  166 static int
  167 hvkbd_poll(keyboard_t *kbd, int on)
  168 {
  169         hv_kbd_sc *sc = kbd->kb_data;
  170 
  171         HVKBD_LOCK();
  172         /*
  173          * Keep a reference count on polling to allow recursive
  174          * cngrab() during a panic for example.
  175          */
  176         if (on)
  177                 sc->sc_polling++;
  178         else if (sc->sc_polling > 0)
  179                 sc->sc_polling--;
  180 
  181         if (sc->sc_polling != 0) {
  182                 sc->sc_flags |= HVKBD_FLAG_POLLING;
  183         } else {
  184                 sc->sc_flags &= ~HVKBD_FLAG_POLLING;
  185         }
  186         HVKBD_UNLOCK();
  187         return (0);
  188 }
  189 
  190 /*
  191  * Enable the access to the device; until this function is called,
  192  * the client cannot read from the keyboard.
  193  */
  194 static int
  195 hvkbd_enable(keyboard_t *kbd)
  196 {
  197         HVKBD_LOCK();
  198         KBD_ACTIVATE(kbd);
  199         HVKBD_UNLOCK();
  200         return (0);
  201 }
  202 
  203 /* disallow the access to the device */
  204 static int
  205 hvkbd_disable(keyboard_t *kbd)
  206 {
  207         DEBUG_HVKBD(kbd, "%s\n", __func__);
  208         HVKBD_LOCK();
  209         KBD_DEACTIVATE(kbd);
  210         HVKBD_UNLOCK();
  211         return (0);
  212 }
  213 
  214 static void
  215 hvkbd_do_poll(hv_kbd_sc *sc, uint8_t wait)
  216 {
  217         while (!hv_kbd_prod_is_ready(sc)) {
  218                 hv_kbd_read_channel(sc->hs_chan, sc);
  219                 if (!wait)
  220                         break;
  221         }
  222 }
  223 
  224 /* check if data is waiting */
  225 /* Currently unused. */
  226 static int
  227 hvkbd_check(keyboard_t *kbd)
  228 {
  229         DEBUG_HVKBD(kbd, "%s\n", __func__);
  230         return (0);
  231 }
  232 
  233 /* check if char is waiting */
  234 static int
  235 hvkbd_check_char_locked(keyboard_t *kbd)
  236 {
  237         HVKBD_LOCK_ASSERT();
  238         if (!KBD_IS_ACTIVE(kbd))
  239                 return (FALSE);
  240 
  241         hv_kbd_sc *sc = kbd->kb_data;
  242         if (!(sc->sc_flags & HVKBD_FLAG_COMPOSE) && sc->sc_composed_char != 0)
  243                 return (TRUE);
  244         if (sc->sc_flags & HVKBD_FLAG_POLLING)
  245                 hvkbd_do_poll(sc, 0);
  246         if (hv_kbd_prod_is_ready(sc)) {
  247                 return (TRUE);
  248         }
  249         return (FALSE);
  250 }
  251 
  252 static int
  253 hvkbd_check_char(keyboard_t *kbd)
  254 {
  255         int result;
  256 
  257         HVKBD_LOCK();
  258         result = hvkbd_check_char_locked(kbd);
  259         HVKBD_UNLOCK();
  260 
  261         return (result);
  262 }
  263 
  264 /* read char from the keyboard */
  265 static uint32_t
  266 hvkbd_read_char_locked(keyboard_t *kbd, int wait)
  267 {
  268         uint32_t scancode = NOKEY;
  269         uint32_t action;
  270         keystroke ks;
  271         hv_kbd_sc *sc = kbd->kb_data;
  272         int keycode;
  273 
  274         HVKBD_LOCK_ASSERT();
  275 
  276         if (!KBD_IS_ACTIVE(kbd) || !hv_kbd_prod_is_ready(sc))
  277                 return (NOKEY);
  278 
  279 next_code:
  280 
  281         /* do we have a composed char to return? */
  282         if (!(sc->sc_flags & HVKBD_FLAG_COMPOSE) && sc->sc_composed_char > 0) {
  283                 action = sc->sc_composed_char;
  284                 sc->sc_composed_char = 0;
  285                 if (action > UCHAR_MAX) {
  286                         return (ERRKEY);
  287                 }
  288                 return (action);
  289         }
  290 
  291         if (hv_kbd_fetch_top(sc, &ks)) {
  292                 return (NOKEY);
  293         }
  294         if ((ks.info & IS_E0) || (ks.info & IS_E1)) {
  295                 /**
  296                  * Emulate the generation of E0 or E1 scancode,
  297                  * the real scancode will be consumed next time.
  298                  */
  299                 if (ks.info & IS_E0) {
  300                         scancode = XTKBD_EMUL0;
  301                         ks.info &= ~IS_E0;
  302                 } else if (ks.info & IS_E1) {
  303                         scancode = XTKBD_EMUL1;
  304                         ks.info &= ~IS_E1;
  305                 }
  306                 /**
  307                  * Change the top item to avoid encountering
  308                  * E0 or E1 twice.
  309                  */
  310                 hv_kbd_modify_top(sc, &ks);
  311         } else if (ks.info & IS_UNICODE) {
  312                 /**
  313                  * XXX: Hyperv host send unicode to VM through
  314                  * 'Type clipboard text', the mapping from
  315                  * unicode to scancode depends on the keymap.
  316                  * It is so complicated that we do not plan to
  317                  * support it yet.
  318                  */
  319                 if (bootverbose)
  320                         device_printf(sc->dev, "Unsupported unicode\n");
  321                 hv_kbd_remove_top(sc);
  322                 return (NOKEY);
  323         } else {
  324                 scancode = ks.makecode;
  325                 if (ks.info & IS_BREAK) {
  326                         scancode |= XTKBD_RELEASE;
  327                 }
  328                 hv_kbd_remove_top(sc);
  329         }
  330 #ifdef EVDEV_SUPPORT
  331         /* push evdev event */
  332         if (evdev_rcpt_mask & EVDEV_RCPT_HW_KBD &&
  333             sc->ks_evdev != NULL) {
  334                 keycode = evdev_scancode2key(&sc->ks_evdev_state,
  335                     scancode);
  336 
  337                 if (keycode != KEY_RESERVED) {
  338                         evdev_push_event(sc->ks_evdev, EV_KEY,
  339                             (uint16_t)keycode, scancode & 0x80 ? 0 : 1);
  340                         evdev_sync(sc->ks_evdev);
  341                 }
  342         }
  343         if (sc->ks_evdev != NULL && evdev_is_grabbed(sc->ks_evdev))
  344                 return (NOKEY);
  345 #endif
  346         ++kbd->kb_count;
  347         DEBUG_HVKBD(kbd, "read scan: 0x%x\n", scancode);
  348 
  349         /* return the byte as is for the K_RAW mode */
  350         if (sc->sc_mode == K_RAW)
  351                 return scancode;
  352 
  353         /* translate the scan code into a keycode */
  354         keycode = scancode & 0x7F;
  355         switch (sc->sc_prefix) {
  356         case 0x00:      /* normal scancode */
  357                 switch(scancode) {
  358                 case 0xB8:      /* left alt (compose key) released */
  359                         if (sc->sc_flags & HVKBD_FLAG_COMPOSE) {
  360                                 sc->sc_flags &= ~HVKBD_FLAG_COMPOSE;
  361                                 if (sc->sc_composed_char > UCHAR_MAX)
  362                                         sc->sc_composed_char = 0;
  363                         }
  364                         break;
  365                 case 0x38:      /* left alt (compose key) pressed */
  366                         if (!(sc->sc_flags & HVKBD_FLAG_COMPOSE)) {
  367                                 sc->sc_flags |= HVKBD_FLAG_COMPOSE;
  368                                 sc->sc_composed_char = 0;
  369                         }
  370                         break;
  371                 case 0xE0:
  372                 case 0xE1:
  373                         sc->sc_prefix = scancode;
  374                         goto next_code;
  375                 }
  376                 break;
  377         case 0xE0:              /* 0xE0 prefix */
  378                 sc->sc_prefix = 0;
  379                 switch (keycode) {
  380                 case 0x1C:      /* right enter key */
  381                         keycode = 0x59;
  382                         break;
  383                 case 0x1D:      /* right ctrl key */
  384                         keycode = 0x5A;
  385                         break;
  386                 case 0x35:      /* keypad divide key */
  387                         keycode = 0x5B;
  388                         break;
  389                 case 0x37:      /* print scrn key */
  390                         keycode = 0x5C;
  391                         break;
  392                 case 0x38:      /* right alt key (alt gr) */
  393                         keycode = 0x5D;
  394                         break;
  395                 case 0x46:      /* ctrl-pause/break on AT 101 (see below) */
  396                         keycode = 0x68;
  397                         break;
  398                 case 0x47:      /* grey home key */
  399                         keycode = 0x5E;
  400                         break;
  401                 case 0x48:      /* grey up arrow key */
  402                         keycode = 0x5F;
  403                         break;
  404                 case 0x49:      /* grey page up key */
  405                         keycode = 0x60;
  406                         break;
  407                 case 0x4B:      /* grey left arrow key */
  408                         keycode = 0x61;
  409                         break;
  410                 case 0x4D:      /* grey right arrow key */
  411                         keycode = 0x62;
  412                         break;
  413                 case 0x4F:      /* grey end key */
  414                         keycode = 0x63;
  415                         break;
  416                 case 0x50:      /* grey down arrow key */
  417                         keycode = 0x64;
  418                         break;
  419                 case 0x51:      /* grey page down key */
  420                         keycode = 0x65;
  421                         break;
  422                 case 0x52:      /* grey insert key */
  423                         keycode = 0x66;
  424                         break;
  425                 case 0x53:      /* grey delete key */
  426                         keycode = 0x67;
  427                         break;
  428                         /* the following 3 are only used on the MS "Natural" keyboard */
  429                 case 0x5b:      /* left Window key */
  430                         keycode = 0x69;
  431                         break;
  432                 case 0x5c:      /* right Window key */
  433                         keycode = 0x6a;
  434                         break;
  435                 case 0x5d:      /* menu key */
  436                         keycode = 0x6b;
  437                         break;
  438                 case 0x5e:      /* power key */
  439                         keycode = 0x6d;
  440                         break;
  441                 case 0x5f:      /* sleep key */
  442                         keycode = 0x6e;
  443                         break;
  444                 case 0x63:      /* wake key */
  445                         keycode = 0x6f;
  446                         break;
  447                 default:        /* ignore everything else */
  448                         goto next_code;
  449                 }
  450                 break;
  451         case 0xE1:      /* 0xE1 prefix */
  452                 /*
  453                  * The pause/break key on the 101 keyboard produces:
  454                  * E1-1D-45 E1-9D-C5
  455                  * Ctrl-pause/break produces:
  456                  * E0-46 E0-C6 (See above.)
  457                  */
  458                 sc->sc_prefix = 0;
  459                 if (keycode == 0x1D)
  460                         sc->sc_prefix = 0x1D;
  461                 goto next_code;
  462                 /* NOT REACHED */
  463         case 0x1D:      /* pause / break */
  464                 sc->sc_prefix = 0;
  465                 if (keycode != 0x45)
  466                         goto next_code;
  467                 keycode = 0x68;
  468                 break;
  469         }
  470 
  471         /* XXX assume 101/102 keys AT keyboard */
  472         switch (keycode) {
  473         case 0x5c:      /* print screen */
  474                 if (sc->sc_flags & ALTS)
  475                         keycode = 0x54; /* sysrq */
  476                 break;
  477         case 0x68:      /* pause/break */
  478                 if (sc->sc_flags & CTLS)
  479                         keycode = 0x6c; /* break */
  480                 break;
  481         }
  482 
  483         /* return the key code in the K_CODE mode */
  484         if (sc->sc_mode == K_CODE)
  485                 return (keycode | (scancode & 0x80));
  486 
  487         /* compose a character code */
  488         if (sc->sc_flags &  HVKBD_FLAG_COMPOSE) {
  489                 switch (keycode | (scancode & 0x80)) {
  490                 /* key pressed, process it */
  491                 case 0x47: case 0x48: case 0x49:        /* keypad 7,8,9 */
  492                         sc->sc_composed_char *= 10;
  493                         sc->sc_composed_char += keycode - 0x40;
  494                         if (sc->sc_composed_char > UCHAR_MAX)
  495                                 return ERRKEY;
  496                         goto next_code;
  497                 case 0x4B: case 0x4C: case 0x4D:        /* keypad 4,5,6 */
  498                         sc->sc_composed_char *= 10;
  499                         sc->sc_composed_char += keycode - 0x47;
  500                         if (sc->sc_composed_char > UCHAR_MAX)
  501                                 return ERRKEY;
  502                         goto next_code;
  503                 case 0x4F: case 0x50: case 0x51:        /* keypad 1,2,3 */
  504                         sc->sc_composed_char *= 10;
  505                         sc->sc_composed_char += keycode - 0x4E;
  506                         if (sc->sc_composed_char > UCHAR_MAX)
  507                                 return ERRKEY;
  508                         goto next_code;
  509                 case 0x52:                              /* keypad 0 */
  510                         sc->sc_composed_char *= 10;
  511                         if (sc->sc_composed_char > UCHAR_MAX)
  512                                 return ERRKEY;
  513                         goto next_code;
  514 
  515                 /* key released, no interest here */
  516                 case 0xC7: case 0xC8: case 0xC9:        /* keypad 7,8,9 */
  517                 case 0xCB: case 0xCC: case 0xCD:        /* keypad 4,5,6 */
  518                 case 0xCF: case 0xD0: case 0xD1:        /* keypad 1,2,3 */
  519                 case 0xD2:                              /* keypad 0 */
  520                         goto next_code;
  521 
  522                 case 0x38:                              /* left alt key */
  523                         break;
  524 
  525                 default:
  526                         if (sc->sc_composed_char > 0) {
  527                                 sc->sc_flags &= ~HVKBD_FLAG_COMPOSE;
  528                                 sc->sc_composed_char = 0;
  529                                 return (ERRKEY);
  530                         }
  531                         break;
  532                 }
  533         }
  534 
  535         /* keycode to key action */
  536         action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
  537                                   &sc->sc_state, &sc->sc_accents);
  538         if (action == NOKEY)
  539                 goto next_code;
  540         else
  541                 return (action);
  542 }
  543 
  544 /* Currently wait is always false. */
  545 static uint32_t
  546 hvkbd_read_char(keyboard_t *kbd, int wait)
  547 {
  548         uint32_t keycode;
  549 
  550         HVKBD_LOCK();
  551         keycode = hvkbd_read_char_locked(kbd, wait);
  552         HVKBD_UNLOCK();
  553 
  554         return (keycode);
  555 }
  556 
  557 /* clear the internal state of the keyboard */
  558 static void
  559 hvkbd_clear_state(keyboard_t *kbd)
  560 {
  561         hv_kbd_sc *sc = kbd->kb_data;
  562         sc->sc_state &= LOCK_MASK;      /* preserve locking key state */
  563         sc->sc_flags &= ~(HVKBD_FLAG_POLLING | HVKBD_FLAG_COMPOSE);
  564         sc->sc_accents = 0;
  565         sc->sc_composed_char = 0;
  566 }
  567 
  568 static int
  569 hvkbd_ioctl_locked(keyboard_t *kbd, u_long cmd, caddr_t arg)
  570 {
  571         int i;
  572 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
  573     defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
  574         int ival;
  575 #endif
  576         hv_kbd_sc *sc = kbd->kb_data;
  577         switch (cmd) {
  578         case KDGKBMODE:
  579                 *(int *)arg = sc->sc_mode;
  580                 break;
  581 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
  582     defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
  583         case _IO('K', 7):
  584                 ival = IOCPARM_IVAL(arg);
  585                 arg = (caddr_t)&ival;
  586                 /* FALLTHROUGH */
  587 #endif
  588         case KDSKBMODE:         /* set keyboard mode */
  589                 DEBUG_HVKBD(kbd, "expected mode: %x\n", *(int *)arg);
  590                 switch (*(int *)arg) {
  591                 case K_XLATE:
  592                         if (sc->sc_mode != K_XLATE) {
  593                                 /* make lock key state and LED state match */
  594                                 sc->sc_state &= ~LOCK_MASK;
  595                                 sc->sc_state |= KBD_LED_VAL(kbd);
  596                         }
  597                         /* FALLTHROUGH */
  598                 case K_RAW:
  599                 case K_CODE:
  600                         if (sc->sc_mode != *(int *)arg) {
  601                                 DEBUG_HVKBD(kbd, "mod changed to %x\n", *(int *)arg);
  602                                 if ((sc->sc_flags & HVKBD_FLAG_POLLING) == 0)
  603                                         hvkbd_clear_state(kbd);
  604                                 sc->sc_mode = *(int *)arg;
  605                         }
  606                         break;
  607                 default:
  608                         return (EINVAL);
  609                 }
  610                 break;
  611         case KDGKBSTATE:        /* get lock key state */
  612                 *(int *)arg = sc->sc_state & LOCK_MASK;
  613                 break;
  614 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
  615     defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
  616         case _IO('K', 20):
  617                 ival = IOCPARM_IVAL(arg);
  618                 arg = (caddr_t)&ival;
  619                 /* FALLTHROUGH */
  620 #endif
  621         case KDSKBSTATE:                /* set lock key state */
  622                 if (*(int *)arg & ~LOCK_MASK) {
  623                         return (EINVAL);
  624                 }
  625                 sc->sc_state &= ~LOCK_MASK;
  626                 sc->sc_state |= *(int *)arg;
  627                 return hvkbd_ioctl_locked(kbd, KDSETLED, arg);
  628         case KDGETLED:                  /* get keyboard LED */
  629                 *(int *)arg = KBD_LED_VAL(kbd);
  630                 break;
  631 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
  632     defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
  633         case _IO('K', 66):
  634                 ival = IOCPARM_IVAL(arg);
  635                 arg = (caddr_t)&ival;
  636                 /* FALLTHROUGH */
  637 #endif
  638         case KDSETLED:                  /* set keyboard LED */
  639                 /* NOTE: lock key state in "sc_state" won't be changed */
  640                 if (*(int *)arg & ~LOCK_MASK)
  641                         return (EINVAL);
  642 
  643                 i = *(int *)arg;
  644 
  645                 /* replace CAPS LED with ALTGR LED for ALTGR keyboards */
  646                 if (sc->sc_mode == K_XLATE &&
  647                     kbd->kb_keymap->n_keys > ALTGR_OFFSET) {
  648                         if (i & ALKED)
  649                                 i |= CLKED;
  650                         else
  651                                 i &= ~CLKED;
  652                 }
  653                 if (KBD_HAS_DEVICE(kbd)) {
  654                         DEBUG_HVSC(sc, "setled 0x%x\n", *(int *)arg);
  655                 }
  656 
  657 #ifdef EVDEV_SUPPORT
  658                 /* push LED states to evdev */
  659                 if (sc->ks_evdev != NULL &&
  660                     evdev_rcpt_mask & EVDEV_RCPT_HW_KBD)
  661                         evdev_push_leds(sc->ks_evdev, *(int *)arg);
  662 #endif
  663                 KBD_LED_VAL(kbd) = *(int *)arg;
  664                 break;
  665         case PIO_KEYMAP:        /* set keyboard translation table */
  666         case OPIO_KEYMAP:       /* set keyboard translation table (compat) */
  667         case PIO_KEYMAPENT:     /* set keyboard translation table entry */
  668         case PIO_DEADKEYMAP:    /* set accent key translation table */
  669                 sc->sc_accents = 0;
  670                 /* FALLTHROUGH */
  671         default:
  672                 return (genkbd_commonioctl(kbd, cmd, arg));
  673         }
  674         return (0);
  675 }
  676 
  677 /* some useful control functions */
  678 static int
  679 hvkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
  680 {
  681         DEBUG_HVKBD(kbd, "%s: %lx start\n", __func__, cmd);
  682         HVKBD_LOCK();
  683         int ret = hvkbd_ioctl_locked(kbd, cmd, arg);
  684         HVKBD_UNLOCK();
  685         DEBUG_HVKBD(kbd, "%s: %lx end %d\n", __func__, cmd, ret);
  686         return (ret);
  687 }
  688 
  689 /* read one byte from the keyboard if it's allowed */
  690 /* Currently unused. */
  691 static int
  692 hvkbd_read(keyboard_t *kbd, int wait)
  693 {
  694         DEBUG_HVKBD(kbd, "%s\n", __func__);
  695         HVKBD_LOCK_ASSERT();
  696         if (!KBD_IS_ACTIVE(kbd))
  697                 return (-1);
  698         return hvkbd_read_char_locked(kbd, wait);
  699 }
  700 
  701 #ifdef EVDEV_SUPPORT
  702 static void
  703 hvkbd_ev_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
  704     int32_t value)
  705 {
  706         keyboard_t *kbd = evdev_get_softc(evdev);
  707 
  708         if (evdev_rcpt_mask & EVDEV_RCPT_HW_KBD &&
  709         (type == EV_LED || type == EV_REP)) {
  710                 mtx_lock(&Giant);
  711                 kbd_ev_event(kbd, type, code, value);
  712                 mtx_unlock(&Giant);
  713         }
  714 }
  715 #endif
  716 
  717 static keyboard_switch_t hvkbdsw = {
  718         .probe =        hvkbd_probe,            /* not used */
  719         .init =         hvkbd_init,
  720         .term =         hvkbd_term,             /* not used */
  721         .intr =         hvkbd_intr,             /* not used */
  722         .test_if =      hvkbd_test_if,          /* not used */
  723         .enable =       hvkbd_enable,
  724         .disable =      hvkbd_disable,
  725         .read =         hvkbd_read,
  726         .check =        hvkbd_check,
  727         .read_char =    hvkbd_read_char,
  728         .check_char =   hvkbd_check_char,
  729         .ioctl =        hvkbd_ioctl,
  730         .lock =         hvkbd_lock,             /* not used */
  731         .clear_state =  hvkbd_clear_state,
  732         .get_state =    hvkbd_get_state,        /* not used */
  733         .set_state =    hvkbd_set_state,        /* not used */
  734         .poll =         hvkbd_poll,
  735 };
  736 
  737 KEYBOARD_DRIVER(hvkbd, hvkbdsw, hvkbd_configure);
  738 
  739 void
  740 hv_kbd_intr(hv_kbd_sc *sc)
  741 {
  742         uint32_t c;
  743         if ((sc->sc_flags & HVKBD_FLAG_POLLING) != 0)
  744                 return;
  745 
  746         if (KBD_IS_ACTIVE(&sc->sc_kbd) &&
  747             KBD_IS_BUSY(&sc->sc_kbd)) {
  748                 /* let the callback function process the input */
  749                 (sc->sc_kbd.kb_callback.kc_func) (&sc->sc_kbd, KBDIO_KEYINPUT,
  750                     sc->sc_kbd.kb_callback.kc_arg);
  751         } else {
  752                 /* read and discard the input, no one is waiting for it */
  753                 do {
  754                         c = hvkbd_read_char(&sc->sc_kbd, 0);
  755                 } while (c != NOKEY);
  756         }
  757 }
  758 
  759 int
  760 hvkbd_driver_load(module_t mod, int what, void *arg)
  761 {
  762         switch (what) {
  763         case MOD_LOAD:
  764                 kbd_add_driver(&hvkbd_kbd_driver);
  765                 break;
  766         case MOD_UNLOAD:
  767                 kbd_delete_driver(&hvkbd_kbd_driver);
  768                 break;
  769         }
  770         return (0);
  771 }
  772 
  773 int
  774 hv_kbd_drv_attach(device_t dev)
  775 {
  776         hv_kbd_sc *sc = device_get_softc(dev);
  777         int unit = device_get_unit(dev);
  778         keyboard_t *kbd = &sc->sc_kbd;
  779         keyboard_switch_t *sw;
  780 #ifdef EVDEV_SUPPORT
  781         struct evdev_dev *evdev;
  782 #endif
  783 
  784         sw = kbd_get_switch(HVKBD_DRIVER_NAME);
  785         if (sw == NULL) {
  786                 return (ENXIO);
  787         }
  788 
  789         kbd_init_struct(kbd, HVKBD_DRIVER_NAME, KB_OTHER, unit, 0, 0, 0);
  790         kbd->kb_data = (void *)sc;
  791         kbd_set_maps(kbd, &key_map, &accent_map, fkey_tab, nitems(fkey_tab));
  792         KBD_FOUND_DEVICE(kbd);
  793         hvkbd_clear_state(kbd);
  794         KBD_PROBE_DONE(kbd);
  795         KBD_INIT_DONE(kbd);
  796         sc->sc_mode = K_XLATE;
  797         (*sw->enable)(kbd);
  798 
  799 #ifdef EVDEV_SUPPORT
  800         evdev = evdev_alloc();
  801         evdev_set_name(evdev, "Hyper-V keyboard");
  802         evdev_set_phys(evdev, device_get_nameunit(dev));
  803         evdev_set_id(evdev, BUS_VIRTUAL, 0, 0, 0);
  804         evdev_set_methods(evdev, kbd, &hvkbd_evdev_methods);
  805         evdev_support_event(evdev, EV_SYN);
  806         evdev_support_event(evdev, EV_KEY);
  807         evdev_support_event(evdev, EV_LED);
  808         evdev_support_event(evdev, EV_REP);
  809         evdev_support_all_known_keys(evdev);
  810         evdev_support_led(evdev, LED_NUML);
  811         evdev_support_led(evdev, LED_CAPSL);
  812         evdev_support_led(evdev, LED_SCROLLL);
  813         if (evdev_register_mtx(evdev, &Giant))
  814                 evdev_free(evdev);
  815         else
  816                 sc->ks_evdev = evdev;
  817         sc->ks_evdev_state = 0;
  818 #endif
  819 
  820         if (kbd_register(kbd) < 0) {
  821                 goto detach;
  822         }
  823         KBD_CONFIG_DONE(kbd);
  824 #ifdef KBD_INSTALL_CDEV
  825         if (kbd_attach(kbd)) {
  826                 goto detach;
  827         }
  828 #endif
  829         if (bootverbose) {
  830                 kbdd_diag(kbd, bootverbose);
  831         }
  832         return (0);
  833 detach:
  834         hv_kbd_drv_detach(dev);
  835         return (ENXIO);
  836 }
  837 
  838 int
  839 hv_kbd_drv_detach(device_t dev)
  840 {
  841         int error = 0;
  842         hv_kbd_sc *sc = device_get_softc(dev);
  843         hvkbd_disable(&sc->sc_kbd);
  844 #ifdef EVDEV_SUPPORT
  845         evdev_free(sc->ks_evdev);
  846 #endif
  847         if (KBD_IS_CONFIGURED(&sc->sc_kbd)) {
  848                 error = kbd_unregister(&sc->sc_kbd);
  849                 if (error) {
  850                         device_printf(dev, "WARNING: kbd_unregister() "
  851                             "returned non-zero! (ignored)\n");
  852                 }
  853         }
  854 #ifdef KBD_INSTALL_CDEV
  855         error = kbd_detach(&sc->sc_kbd);
  856 #endif
  857         return (error);
  858 }
  859 

Cache object: 0ae25c35ed02bbd29cc7f827b40ffc3a


[ 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.