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/vkbd/vkbd.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  * vkbd.c
    3  *
    4  * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com>
    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  * $Id: vkbd.c,v 1.20 2004/11/15 23:53:30 max Exp $
   29  * $FreeBSD: releng/6.0/sys/dev/vkbd/vkbd.c 149038 2005-08-13 21:24:18Z rwatson $
   30  */
   31 
   32 #include "opt_kbd.h"
   33 
   34 #include <sys/param.h>
   35 #include <sys/conf.h>
   36 #include <sys/fcntl.h>
   37 #include <sys/kbio.h>
   38 #include <sys/kernel.h>
   39 #include <sys/limits.h>
   40 #include <sys/lock.h>
   41 #include <sys/malloc.h>
   42 #include <sys/module.h>
   43 #include <sys/mutex.h>
   44 #include <sys/poll.h>
   45 #include <sys/proc.h>
   46 #include <sys/queue.h>
   47 #include <sys/selinfo.h>
   48 #include <sys/systm.h>
   49 #include <sys/taskqueue.h>
   50 #include <sys/uio.h>
   51 #include <dev/kbd/kbdreg.h>
   52 #include <dev/kbd/kbdtables.h>
   53 #include <dev/vkbd/vkbd_var.h>
   54 
   55 #define DEVICE_NAME     "vkbdctl"
   56 #define KEYBOARD_NAME   "vkbd"
   57 
   58 MALLOC_DECLARE(M_VKBD);
   59 MALLOC_DEFINE(M_VKBD, KEYBOARD_NAME, "Virtual AT keyboard");
   60 
   61 /*****************************************************************************
   62  *****************************************************************************
   63  **                             Keyboard state
   64  *****************************************************************************
   65  *****************************************************************************/
   66 
   67 #define VKBD_LOCK_DECL          struct mtx ks_lock
   68 #define VKBD_LOCK_INIT(s)       mtx_init(&(s)->ks_lock, "vkbd_lock", NULL, MTX_DEF|MTX_RECURSE)
   69 #define VKBD_LOCK_DESTROY(s)    mtx_destroy(&(s)->ks_lock)
   70 #define VKBD_LOCK(s)            mtx_lock(&(s)->ks_lock)
   71 #define VKBD_UNLOCK(s)          mtx_unlock(&(s)->ks_lock)
   72 #define VKBD_LOCK_ASSERT(s, w)  mtx_assert(&(s)->ks_lock, w)
   73 #define VKBD_SLEEP(s, f, d, t) \
   74         msleep(&(s)->f, &(s)->ks_lock, PCATCH | (PZERO + 1), d, t)
   75 
   76 #define VKBD_KEYBOARD(d) \
   77         kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, dev2unit(d)))
   78 
   79 /* vkbd queue */
   80 struct vkbd_queue
   81 {
   82         int             q[VKBD_Q_SIZE]; /* queue */
   83         int             head;           /* index of the first code */
   84         int             tail;           /* index of the last code */
   85         int             cc;             /* number of codes in queue */
   86 };
   87 
   88 typedef struct vkbd_queue       vkbd_queue_t;
   89 
   90 /* vkbd state */
   91 struct vkbd_state
   92 {
   93         struct cdev     *ks_dev;        /* control device */
   94 
   95         struct selinfo   ks_rsel;       /* select(2) */
   96         struct selinfo   ks_wsel;
   97 
   98         vkbd_queue_t     ks_inq;        /* input key codes queue */
   99         struct task      ks_task;       /* interrupt task */
  100 
  101         int              ks_flags;      /* flags */
  102 #define OPEN            (1 << 0)        /* control device is open */
  103 #define COMPOSE         (1 << 1)        /* compose flag */
  104 #define STATUS          (1 << 2)        /* status has changed */
  105 #define TASK            (1 << 3)        /* interrupt task queued */
  106 #define READ            (1 << 4)        /* read pending */
  107 #define WRITE           (1 << 5)        /* write pending */
  108 
  109         int              ks_mode;       /* K_XLATE, K_RAW, K_CODE */
  110         int              ks_polling;    /* polling flag */
  111         int              ks_state;      /* shift/lock key state */
  112         int              ks_accents;    /* accent key index (> 0) */
  113         u_int            ks_composed_char; /* composed char code */
  114         u_char           ks_prefix;     /* AT scan code prefix */
  115 
  116         VKBD_LOCK_DECL;
  117 };
  118 
  119 typedef struct vkbd_state       vkbd_state_t;
  120 
  121 /*****************************************************************************
  122  *****************************************************************************
  123  **                             Character device
  124  *****************************************************************************
  125  *****************************************************************************/
  126 
  127 static void             vkbd_dev_clone(void *, struct ucred *, char *, int,
  128                             struct cdev **);
  129 static d_open_t         vkbd_dev_open;
  130 static d_close_t        vkbd_dev_close;
  131 static d_read_t         vkbd_dev_read;
  132 static d_write_t        vkbd_dev_write;
  133 static d_ioctl_t        vkbd_dev_ioctl;
  134 static d_poll_t         vkbd_dev_poll;
  135 static void             vkbd_dev_intr(void *, int);
  136 static void             vkbd_status_changed(vkbd_state_t *);
  137 static int              vkbd_data_ready(vkbd_state_t *);
  138 static int              vkbd_data_read(vkbd_state_t *, int);
  139 
  140 static struct cdevsw    vkbd_dev_cdevsw = {
  141         .d_version =    D_VERSION,
  142         .d_flags =      D_PSEUDO | D_NEEDGIANT,
  143         .d_open =       vkbd_dev_open,
  144         .d_close =      vkbd_dev_close,
  145         .d_read =       vkbd_dev_read,
  146         .d_write =      vkbd_dev_write,
  147         .d_ioctl =      vkbd_dev_ioctl,
  148         .d_poll =       vkbd_dev_poll,
  149         .d_name =       DEVICE_NAME,
  150 };
  151 
  152 static struct clonedevs *vkbd_dev_clones = NULL;
  153 
  154 /* Clone device */
  155 static void
  156 vkbd_dev_clone(void *arg, struct ucred *cred, char *name, int namelen,
  157     struct cdev **dev)
  158 {
  159         int     unit;
  160 
  161         if (*dev != NULL)
  162                 return;
  163 
  164         if (strcmp(name, DEVICE_NAME) == 0)
  165                 unit = -1;
  166         else if (dev_stdclone(name, NULL, DEVICE_NAME, &unit) != 1)
  167                 return; /* don't recognize the name */
  168 
  169         /* find any existing device, or allocate new unit number */
  170         if (clone_create(&vkbd_dev_clones, &vkbd_dev_cdevsw, &unit, dev, 0)) {
  171                 *dev = make_dev(&vkbd_dev_cdevsw, unit2minor(unit),
  172                         UID_ROOT, GID_WHEEL, 0600, DEVICE_NAME "%d", unit);
  173                 if (*dev != NULL) {
  174                         dev_ref(*dev);
  175                         (*dev)->si_flags |= SI_CHEAPCLONE;
  176                 }
  177         }
  178 }
  179 
  180 /* Open device */
  181 static int
  182 vkbd_dev_open(struct cdev *dev, int flag, int mode, struct thread *td)
  183 {
  184         int                      unit = dev2unit(dev), error;
  185         keyboard_switch_t       *sw = NULL;
  186         keyboard_t              *kbd = NULL;
  187         vkbd_state_t            *state = (vkbd_state_t *) dev->si_drv1;
  188 
  189         /* XXX FIXME: dev->si_drv1 locking */
  190         if (state == NULL) {
  191                 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL)
  192                         return (ENXIO);
  193 
  194                 if ((error = (*sw->probe)(unit, NULL, 0)) != 0 ||
  195                     (error = (*sw->init)(unit, &kbd, NULL, 0)) != 0)
  196                         return (error);
  197 
  198                 state = (vkbd_state_t *) kbd->kb_data;
  199 
  200                 if ((error = (*sw->enable)(kbd)) != 0) {
  201                         (*sw->term)(kbd);
  202                         return (error);
  203                 }
  204 
  205 #ifdef KBD_INSTALL_CDEV
  206                 if ((error = kbd_attach(kbd)) != 0) {
  207                         (*sw->disable)(kbd);
  208                         (*sw->term)(kbd);
  209                         return (error);
  210                 }
  211 #endif /* def KBD_INSTALL_CDEV */
  212 
  213                 dev->si_drv1 = kbd->kb_data;
  214         }
  215 
  216         VKBD_LOCK(state);
  217 
  218         if (state->ks_flags & OPEN) {
  219                 VKBD_UNLOCK(state);
  220                 return (EBUSY);
  221         }
  222 
  223         state->ks_flags |= OPEN;
  224         state->ks_dev = dev;
  225 
  226         VKBD_UNLOCK(state);
  227 
  228         return (0);
  229 }
  230 
  231 /* Close device */
  232 static int
  233 vkbd_dev_close(struct cdev *dev, int foo, int bar, struct thread *td)
  234 {
  235         keyboard_t      *kbd = VKBD_KEYBOARD(dev);
  236         vkbd_state_t    *state = NULL;
  237 
  238         if (kbd == NULL)
  239                 return (ENXIO);
  240 
  241         if (kbd->kb_data == NULL || kbd->kb_data != dev->si_drv1)
  242                 panic("%s: kbd->kb_data != dev->si_drv1\n", __func__);
  243 
  244         state = (vkbd_state_t *) kbd->kb_data;
  245 
  246         VKBD_LOCK(state);
  247 
  248         /* wait for interrupt task */
  249         while (state->ks_flags & TASK)
  250                 VKBD_SLEEP(state, ks_task, "vkbdc", 0);
  251 
  252         /* wakeup poll()ers */
  253         selwakeuppri(&state->ks_rsel, PZERO + 1);
  254         selwakeuppri(&state->ks_wsel, PZERO + 1);
  255 
  256         state->ks_flags &= ~OPEN;
  257         state->ks_dev = NULL;
  258         state->ks_inq.head = state->ks_inq.tail = state->ks_inq.cc = 0;
  259 
  260         VKBD_UNLOCK(state);
  261 
  262         (*kbdsw[kbd->kb_index]->disable)(kbd);
  263 #ifdef KBD_INSTALL_CDEV
  264         kbd_detach(kbd);
  265 #endif /* def KBD_INSTALL_CDEV */
  266         (*kbdsw[kbd->kb_index]->term)(kbd);
  267 
  268         /* XXX FIXME: dev->si_drv1 locking */
  269         dev->si_drv1 = NULL;
  270 
  271         return (0);
  272 }
  273 
  274 /* Read status */
  275 static int
  276 vkbd_dev_read(struct cdev *dev, struct uio *uio, int flag)
  277 {
  278         keyboard_t      *kbd = VKBD_KEYBOARD(dev);
  279         vkbd_state_t    *state = NULL;
  280         vkbd_status_t    status;
  281         int              error;
  282 
  283         if (kbd == NULL)
  284                 return (ENXIO);
  285 
  286         if (uio->uio_resid != sizeof(status))
  287                 return (EINVAL);
  288 
  289         if (kbd->kb_data == NULL || kbd->kb_data != dev->si_drv1)
  290                 panic("%s: kbd->kb_data != dev->si_drv1\n", __func__);
  291 
  292         state = (vkbd_state_t *) kbd->kb_data;
  293 
  294         VKBD_LOCK(state);
  295 
  296         if (state->ks_flags & READ) {
  297                 VKBD_UNLOCK(state);
  298                 return (EALREADY);
  299         }
  300 
  301         state->ks_flags |= READ;
  302 again:
  303         if (state->ks_flags & STATUS) {
  304                 state->ks_flags &= ~STATUS;
  305 
  306                 status.mode = state->ks_mode;
  307                 status.leds = KBD_LED_VAL(kbd);
  308                 status.lock = state->ks_state & LOCK_MASK;
  309                 status.delay = kbd->kb_delay1;
  310                 status.rate = kbd->kb_delay2;
  311                 bzero(status.reserved, sizeof(status.reserved));
  312 
  313                 error = uiomove(&status, sizeof(status), uio);
  314         } else {
  315                 if (flag & O_NONBLOCK) {
  316                         error = EWOULDBLOCK;
  317                         goto done;
  318                 }
  319 
  320                 error = VKBD_SLEEP(state, ks_flags, "vkbdr", 0);
  321                 if (error != 0) 
  322                         goto done;
  323 
  324                 goto again;
  325         }
  326 done:
  327         state->ks_flags &= ~READ;
  328 
  329         VKBD_UNLOCK(state);
  330         
  331         return (error);
  332 }
  333 
  334 /* Write scancodes */
  335 static int
  336 vkbd_dev_write(struct cdev *dev, struct uio *uio, int flag)
  337 {
  338         keyboard_t      *kbd = VKBD_KEYBOARD(dev);
  339         vkbd_state_t    *state = NULL;
  340         vkbd_queue_t    *q = NULL;
  341         int              error, avail, bytes;
  342 
  343         if (kbd == NULL)
  344                 return (ENXIO);
  345 
  346         if (uio->uio_resid <= 0)
  347                 return (EINVAL);
  348 
  349         if (kbd->kb_data == NULL || kbd->kb_data != dev->si_drv1)
  350                 panic("%s: kbd->kb_data != dev->si_drv1\n", __func__);
  351 
  352         state = (vkbd_state_t *) kbd->kb_data;
  353 
  354         VKBD_LOCK(state);
  355 
  356         if (state->ks_flags & WRITE) {
  357                 VKBD_UNLOCK(state);
  358                 return (EALREADY);
  359         }
  360 
  361         state->ks_flags |= WRITE;
  362         error = 0;
  363         q = &state->ks_inq;
  364 
  365         while (uio->uio_resid >= sizeof(q->q[0])) {
  366                 if (q->head == q->tail) {
  367                         if (q->cc == 0)
  368                                 avail = sizeof(q->q)/sizeof(q->q[0]) - q->head;
  369                         else
  370                                 avail = 0; /* queue must be full */
  371                 } else if (q->head < q->tail)
  372                         avail = sizeof(q->q)/sizeof(q->q[0]) - q->tail;
  373                 else
  374                         avail = q->head - q->tail;
  375 
  376                 if (avail == 0) {
  377                         if (flag & O_NONBLOCK) {
  378                                 error = EWOULDBLOCK;
  379                                 break;
  380                         }
  381 
  382                         error = VKBD_SLEEP(state, ks_inq, "vkbdw", 0);
  383                         if (error != 0)
  384                                 break;
  385                 } else {
  386                         bytes = avail * sizeof(q->q[0]);
  387                         if (bytes > uio->uio_resid) {
  388                                 avail = uio->uio_resid / sizeof(q->q[0]);
  389                                 bytes = avail * sizeof(q->q[0]);
  390                         }
  391 
  392                         error = uiomove((void *) &q->q[q->tail], bytes, uio);
  393                         if (error != 0)
  394                                 break;
  395 
  396                         q->cc += avail;
  397                         q->tail += avail;
  398                         if (q->tail == sizeof(q->q)/sizeof(q->q[0]))
  399                                 q->tail = 0;
  400 
  401                         /* queue interrupt task if needed */
  402                         if (!(state->ks_flags & TASK) &&
  403                             taskqueue_enqueue(taskqueue_swi_giant, &state->ks_task) == 0)
  404                                 state->ks_flags |= TASK;
  405                 }
  406         }
  407 
  408         state->ks_flags &= ~WRITE;
  409 
  410         VKBD_UNLOCK(state);
  411 
  412         return (error);
  413 }
  414 
  415 /* Process ioctl */
  416 static int
  417 vkbd_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
  418 {
  419         keyboard_t      *kbd = VKBD_KEYBOARD(dev);
  420 
  421         return ((kbd == NULL)? ENXIO : 
  422                         (*kbdsw[kbd->kb_index]->ioctl)(kbd, cmd, data));
  423 }
  424 
  425 /* Poll device */
  426 static int
  427 vkbd_dev_poll(struct cdev *dev, int events, struct thread *td)
  428 {
  429         vkbd_state_t    *state = (vkbd_state_t *) dev->si_drv1;
  430         vkbd_queue_t    *q = NULL;
  431         int              revents = 0;
  432 
  433         if (state == NULL)
  434                 return (ENXIO);
  435 
  436         VKBD_LOCK(state);
  437 
  438         q = &state->ks_inq;
  439 
  440         if (events & (POLLIN | POLLRDNORM)) {
  441                 if (state->ks_flags & STATUS)
  442                         revents |= events & (POLLIN | POLLRDNORM);
  443                 else
  444                         selrecord(td, &state->ks_rsel);
  445         }
  446 
  447         if (events & (POLLOUT | POLLWRNORM)) {
  448                 if (q->cc < sizeof(q->q)/sizeof(q->q[0]))
  449                         revents |= events & (POLLOUT | POLLWRNORM);
  450                 else
  451                         selrecord(td, &state->ks_wsel);
  452         }
  453 
  454         VKBD_UNLOCK(state);
  455 
  456         return (revents);
  457 }
  458 
  459 /* Interrupt handler */
  460 void
  461 vkbd_dev_intr(void *xkbd, int pending)
  462 {
  463         keyboard_t      *kbd = (keyboard_t *) xkbd;
  464         vkbd_state_t    *state = (vkbd_state_t *) kbd->kb_data;
  465 
  466         (*kbdsw[kbd->kb_index]->intr)(kbd, NULL);
  467 
  468         VKBD_LOCK(state);
  469 
  470         state->ks_flags &= ~TASK;
  471         wakeup(&state->ks_task);
  472 
  473         VKBD_UNLOCK(state);
  474 }
  475 
  476 /* Set status change flags */
  477 static void
  478 vkbd_status_changed(vkbd_state_t *state)
  479 {
  480         VKBD_LOCK_ASSERT(state, MA_OWNED);
  481 
  482         if (!(state->ks_flags & STATUS)) {
  483                 state->ks_flags |= STATUS;
  484                 selwakeuppri(&state->ks_rsel, PZERO + 1);
  485                 wakeup(&state->ks_flags);
  486         }
  487 }
  488 
  489 /* Check if we have data in the input queue */
  490 static int
  491 vkbd_data_ready(vkbd_state_t *state)
  492 {
  493         VKBD_LOCK_ASSERT(state, MA_OWNED);
  494 
  495         return (state->ks_inq.cc > 0);
  496 }
  497 
  498 /* Read one code from the input queue */
  499 static int
  500 vkbd_data_read(vkbd_state_t *state, int wait)
  501 {
  502         vkbd_queue_t    *q = &state->ks_inq;
  503         int              c;
  504 
  505         VKBD_LOCK_ASSERT(state, MA_OWNED);
  506 
  507         if (q->cc == 0)
  508                 return (-1);
  509 
  510         /* get first code from the queue */
  511         q->cc --;
  512         c = q->q[q->head ++];
  513         if (q->head == sizeof(q->q)/sizeof(q->q[0]))
  514                 q->head = 0;
  515 
  516         /* wakeup ks_inq writers/poll()ers */
  517         selwakeuppri(&state->ks_wsel, PZERO + 1);
  518         wakeup(q);
  519 
  520         return (c);
  521 }
  522 
  523 /****************************************************************************
  524  ****************************************************************************
  525  **                              Keyboard driver
  526  ****************************************************************************
  527  ****************************************************************************/
  528 
  529 static int              vkbd_configure(int flags);
  530 static kbd_probe_t      vkbd_probe;
  531 static kbd_init_t       vkbd_init;
  532 static kbd_term_t       vkbd_term;
  533 static kbd_intr_t       vkbd_intr;
  534 static kbd_test_if_t    vkbd_test_if;
  535 static kbd_enable_t     vkbd_enable;
  536 static kbd_disable_t    vkbd_disable;
  537 static kbd_read_t       vkbd_read;
  538 static kbd_check_t      vkbd_check;
  539 static kbd_read_char_t  vkbd_read_char;
  540 static kbd_check_char_t vkbd_check_char;
  541 static kbd_ioctl_t      vkbd_ioctl;
  542 static kbd_lock_t       vkbd_lock;
  543 static void             vkbd_clear_state_locked(vkbd_state_t *state);
  544 static kbd_clear_state_t vkbd_clear_state;
  545 static kbd_get_state_t  vkbd_get_state;
  546 static kbd_set_state_t  vkbd_set_state;
  547 static kbd_poll_mode_t  vkbd_poll;
  548 
  549 static keyboard_switch_t vkbdsw = {
  550         .probe =        vkbd_probe,
  551         .init =         vkbd_init,
  552         .term =         vkbd_term,
  553         .intr =         vkbd_intr,
  554         .test_if =      vkbd_test_if,
  555         .enable =       vkbd_enable,
  556         .disable =      vkbd_disable,
  557         .read =         vkbd_read,
  558         .check =        vkbd_check,
  559         .read_char =    vkbd_read_char,
  560         .check_char =   vkbd_check_char,
  561         .ioctl =        vkbd_ioctl,
  562         .lock =         vkbd_lock,
  563         .clear_state =  vkbd_clear_state,
  564         .get_state =    vkbd_get_state,
  565         .set_state =    vkbd_set_state,
  566         .get_fkeystr =  genkbd_get_fkeystr,
  567         .poll =         vkbd_poll,
  568         .diag =         genkbd_diag,
  569 };
  570 
  571 static int      typematic(int delay, int rate);
  572 static int      typematic_delay(int delay);
  573 static int      typematic_rate(int rate);
  574 
  575 /* Return the number of found keyboards */
  576 static int
  577 vkbd_configure(int flags)
  578 {
  579         return (1);
  580 }
  581 
  582 /* Detect a keyboard */
  583 static int
  584 vkbd_probe(int unit, void *arg, int flags)
  585 {
  586         return (0);
  587 }
  588 
  589 /* Reset and initialize the keyboard (stolen from atkbd.c) */
  590 static int
  591 vkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
  592 {
  593         keyboard_t      *kbd = NULL;
  594         vkbd_state_t    *state = NULL;
  595         keymap_t        *keymap = NULL;
  596         accentmap_t     *accmap = NULL;
  597         fkeytab_t       *fkeymap = NULL;
  598         int              fkeymap_size, delay[2];
  599         int              error, needfree;
  600 
  601         if (*kbdp == NULL) {
  602                 *kbdp = kbd = malloc(sizeof(*kbd), M_VKBD, M_NOWAIT | M_ZERO);
  603                 state = malloc(sizeof(*state), M_VKBD, M_NOWAIT | M_ZERO);
  604                 keymap = malloc(sizeof(key_map), M_VKBD, M_NOWAIT);
  605                 accmap = malloc(sizeof(accent_map), M_VKBD, M_NOWAIT);
  606                 fkeymap = malloc(sizeof(fkey_tab), M_VKBD, M_NOWAIT);
  607                 fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
  608                 needfree = 1;
  609                 if ((kbd == NULL) || (state == NULL) || (keymap == NULL) ||
  610                     (accmap == NULL) || (fkeymap == NULL)) {
  611                         error = ENOMEM;
  612                         goto bad;
  613                 }
  614 
  615                 VKBD_LOCK_INIT(state);
  616                 state->ks_inq.head = state->ks_inq.tail = state->ks_inq.cc = 0;
  617                 TASK_INIT(&state->ks_task, 0, vkbd_dev_intr, (void *) kbd);
  618         } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
  619                 return (0);
  620         } else {
  621                 kbd = *kbdp;
  622                 state = (vkbd_state_t *) kbd->kb_data;
  623                 keymap = kbd->kb_keymap;
  624                 accmap = kbd->kb_accentmap;
  625                 fkeymap = kbd->kb_fkeytab;
  626                 fkeymap_size = kbd->kb_fkeytab_size;
  627                 needfree = 0;
  628         }
  629 
  630         if (!KBD_IS_PROBED(kbd)) {
  631                 kbd_init_struct(kbd, KEYBOARD_NAME, KB_OTHER, unit, flags, 0, 0);
  632                 bcopy(&key_map, keymap, sizeof(key_map));
  633                 bcopy(&accent_map, accmap, sizeof(accent_map));
  634                 bcopy(fkey_tab, fkeymap,
  635                         imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
  636                 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
  637                 kbd->kb_data = (void *)state;
  638         
  639                 KBD_FOUND_DEVICE(kbd);
  640                 KBD_PROBE_DONE(kbd);
  641 
  642                 VKBD_LOCK(state);
  643                 vkbd_clear_state_locked(state);
  644                 state->ks_mode = K_XLATE;
  645                 /* FIXME: set the initial value for lock keys in ks_state */
  646                 VKBD_UNLOCK(state);
  647         }
  648         if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
  649                 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
  650 
  651                 vkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
  652                 delay[0] = kbd->kb_delay1;
  653                 delay[1] = kbd->kb_delay2;
  654                 vkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
  655 
  656                 KBD_INIT_DONE(kbd);
  657         }
  658         if (!KBD_IS_CONFIGURED(kbd)) {
  659                 if (kbd_register(kbd) < 0) {
  660                         error = ENXIO;
  661                         goto bad;
  662                 }
  663                 KBD_CONFIG_DONE(kbd);
  664         }
  665 
  666         return (0);
  667 bad:
  668         if (needfree) {
  669                 if (state != NULL)
  670                         free(state, M_VKBD);
  671                 if (keymap != NULL)
  672                         free(keymap, M_VKBD);
  673                 if (accmap != NULL)
  674                         free(accmap, M_VKBD);
  675                 if (fkeymap != NULL)
  676                         free(fkeymap, M_VKBD);
  677                 if (kbd != NULL) {
  678                         free(kbd, M_VKBD);
  679                         *kbdp = NULL;   /* insure ref doesn't leak to caller */
  680                 }
  681         }
  682         return (error);
  683 }
  684 
  685 /* Finish using this keyboard */
  686 static int
  687 vkbd_term(keyboard_t *kbd)
  688 {
  689         vkbd_state_t    *state = (vkbd_state_t *) kbd->kb_data;
  690 
  691         kbd_unregister(kbd);
  692 
  693         VKBD_LOCK_DESTROY(state);
  694         bzero(state, sizeof(*state));
  695         free(state, M_VKBD);
  696 
  697         free(kbd->kb_keymap, M_VKBD);
  698         free(kbd->kb_accentmap, M_VKBD);
  699         free(kbd->kb_fkeytab, M_VKBD);
  700         free(kbd, M_VKBD);
  701 
  702         return (0);
  703 }
  704 
  705 /* Keyboard interrupt routine */
  706 static int
  707 vkbd_intr(keyboard_t *kbd, void *arg)
  708 {
  709         int     c;
  710 
  711         if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
  712                 /* let the callback function to process the input */
  713                 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
  714                                             kbd->kb_callback.kc_arg);
  715         } else {
  716                 /* read and discard the input; no one is waiting for input */
  717                 do {
  718                         c = vkbd_read_char(kbd, FALSE);
  719                 } while (c != NOKEY);
  720         }
  721 
  722         return (0);
  723 }
  724 
  725 /* Test the interface to the device */
  726 static int
  727 vkbd_test_if(keyboard_t *kbd)
  728 {
  729         return (0);
  730 }
  731 
  732 /* 
  733  * Enable the access to the device; until this function is called,
  734  * the client cannot read from the keyboard.
  735  */
  736 
  737 static int
  738 vkbd_enable(keyboard_t *kbd)
  739 {
  740         KBD_ACTIVATE(kbd);
  741         return (0);
  742 }
  743 
  744 /* Disallow the access to the device */
  745 static int
  746 vkbd_disable(keyboard_t *kbd)
  747 {
  748         KBD_DEACTIVATE(kbd);
  749         return (0);
  750 }
  751 
  752 /* Read one byte from the keyboard if it's allowed */
  753 static int
  754 vkbd_read(keyboard_t *kbd, int wait)
  755 {
  756         vkbd_state_t    *state = (vkbd_state_t *) kbd->kb_data;
  757         int              c;
  758 
  759         VKBD_LOCK(state);
  760         c = vkbd_data_read(state, wait);
  761         VKBD_UNLOCK(state);
  762 
  763         if (c != -1)
  764                 kbd->kb_count ++;
  765 
  766         return (KBD_IS_ACTIVE(kbd)? c : -1);
  767 }
  768 
  769 /* Check if data is waiting */
  770 static int
  771 vkbd_check(keyboard_t *kbd)
  772 {
  773         vkbd_state_t    *state = NULL;
  774         int              ready;
  775 
  776         if (!KBD_IS_ACTIVE(kbd))
  777                 return (FALSE);
  778 
  779         state = (vkbd_state_t *) kbd->kb_data;
  780 
  781         VKBD_LOCK(state);
  782         ready = vkbd_data_ready(state);
  783         VKBD_UNLOCK(state);
  784 
  785         return (ready);
  786 }
  787 
  788 /* Read char from the keyboard (stolen from atkbd.c) */
  789 static u_int
  790 vkbd_read_char(keyboard_t *kbd, int wait)
  791 {
  792         vkbd_state_t    *state = (vkbd_state_t *) kbd->kb_data;
  793         u_int            action;
  794         int              scancode, keycode;
  795 
  796         VKBD_LOCK(state);
  797 
  798 next_code:
  799 
  800         /* do we have a composed char to return? */
  801         if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
  802                 action = state->ks_composed_char;
  803                 state->ks_composed_char = 0;
  804                 if (action > UCHAR_MAX) {
  805                         VKBD_UNLOCK(state);
  806                         return (ERRKEY);
  807                 }
  808 
  809                 VKBD_UNLOCK(state);
  810                 return (action);
  811         }
  812 
  813         /* see if there is something in the keyboard port */
  814         scancode = vkbd_data_read(state, wait);
  815         if (scancode == -1) {
  816                 VKBD_UNLOCK(state);
  817                 return (NOKEY);
  818         }
  819         /* XXX FIXME: check for -1 if wait == 1! */
  820 
  821         kbd->kb_count ++;
  822 
  823         /* return the byte as is for the K_RAW mode */
  824         if (state->ks_mode == K_RAW) {
  825                 VKBD_UNLOCK(state);
  826                 return (scancode);
  827         }
  828 
  829         /* translate the scan code into a keycode */
  830         keycode = scancode & 0x7F;
  831         switch (state->ks_prefix) {
  832         case 0x00:      /* normal scancode */
  833                 switch(scancode) {
  834                 case 0xB8:      /* left alt (compose key) released */
  835                         if (state->ks_flags & COMPOSE) {
  836                                 state->ks_flags &= ~COMPOSE;
  837                                 if (state->ks_composed_char > UCHAR_MAX)
  838                                         state->ks_composed_char = 0;
  839                         }
  840                         break;
  841                 case 0x38:      /* left alt (compose key) pressed */
  842                         if (!(state->ks_flags & COMPOSE)) {
  843                                 state->ks_flags |= COMPOSE;
  844                                 state->ks_composed_char = 0;
  845                         }
  846                         break;
  847                 case 0xE0:
  848                 case 0xE1:
  849                         state->ks_prefix = scancode;
  850                         goto next_code;
  851                 }
  852                 break;
  853         case 0xE0:      /* 0xE0 prefix */
  854                 state->ks_prefix = 0;
  855                 switch (keycode) {
  856                 case 0x1C:      /* right enter key */
  857                         keycode = 0x59;
  858                         break;
  859                 case 0x1D:      /* right ctrl key */
  860                         keycode = 0x5A;
  861                         break;
  862                 case 0x35:      /* keypad divide key */
  863                         keycode = 0x5B;
  864                         break;
  865                 case 0x37:      /* print scrn key */
  866                         keycode = 0x5C;
  867                         break;
  868                 case 0x38:      /* right alt key (alt gr) */
  869                         keycode = 0x5D;
  870                         break;
  871                 case 0x46:      /* ctrl-pause/break on AT 101 (see below) */
  872                         keycode = 0x68;
  873                         break;
  874                 case 0x47:      /* grey home key */
  875                         keycode = 0x5E;
  876                         break;
  877                 case 0x48:      /* grey up arrow key */
  878                         keycode = 0x5F;
  879                         break;
  880                 case 0x49:      /* grey page up key */
  881                         keycode = 0x60;
  882                         break;
  883                 case 0x4B:      /* grey left arrow key */
  884                         keycode = 0x61;
  885                         break;
  886                 case 0x4D:      /* grey right arrow key */
  887                         keycode = 0x62;
  888                         break;
  889                 case 0x4F:      /* grey end key */
  890                         keycode = 0x63;
  891                         break;
  892                 case 0x50:      /* grey down arrow key */
  893                         keycode = 0x64;
  894                         break;
  895                 case 0x51:      /* grey page down key */
  896                         keycode = 0x65;
  897                         break;
  898                 case 0x52:      /* grey insert key */
  899                         keycode = 0x66;
  900                         break;
  901                 case 0x53:      /* grey delete key */
  902                         keycode = 0x67;
  903                         break;
  904                 /* the following 3 are only used on the MS "Natural" keyboard */
  905                 case 0x5b:      /* left Window key */
  906                         keycode = 0x69;
  907                         break;
  908                 case 0x5c:      /* right Window key */
  909                         keycode = 0x6a;
  910                         break;
  911                 case 0x5d:      /* menu key */
  912                         keycode = 0x6b;
  913                         break;
  914                 case 0x5e:      /* power key */
  915                         keycode = 0x6d;
  916                         break;
  917                 case 0x5f:      /* sleep key */
  918                         keycode = 0x6e;
  919                         break;
  920                 case 0x63:      /* wake key */
  921                         keycode = 0x6f;
  922                         break;
  923                 default:        /* ignore everything else */
  924                         goto next_code;
  925                 }
  926                 break;
  927         case 0xE1:      /* 0xE1 prefix */
  928                 /* 
  929                  * The pause/break key on the 101 keyboard produces:
  930                  * E1-1D-45 E1-9D-C5
  931                  * Ctrl-pause/break produces:
  932                  * E0-46 E0-C6 (See above.)
  933                  */
  934                 state->ks_prefix = 0;
  935                 if (keycode == 0x1D)
  936                         state->ks_prefix = 0x1D;
  937                 goto next_code;
  938                 /* NOT REACHED */
  939         case 0x1D:      /* pause / break */
  940                 state->ks_prefix = 0;
  941                 if (keycode != 0x45)
  942                         goto next_code;
  943                 keycode = 0x68;
  944                 break;
  945         }
  946 
  947         if (kbd->kb_type == KB_84) {
  948                 switch (keycode) {
  949                 case 0x37:      /* *(numpad)/print screen */
  950                         if (state->ks_flags & SHIFTS)
  951                                 keycode = 0x5c; /* print screen */
  952                         break;
  953                 case 0x45:      /* num lock/pause */
  954                         if (state->ks_flags & CTLS)
  955                                 keycode = 0x68; /* pause */
  956                         break;
  957                 case 0x46:      /* scroll lock/break */
  958                         if (state->ks_flags & CTLS)
  959                                 keycode = 0x6c; /* break */
  960                         break;
  961                 }
  962         } else if (kbd->kb_type == KB_101) {
  963                 switch (keycode) {
  964                 case 0x5c:      /* print screen */
  965                         if (state->ks_flags & ALTS)
  966                                 keycode = 0x54; /* sysrq */
  967                         break;
  968                 case 0x68:      /* pause/break */
  969                         if (state->ks_flags & CTLS)
  970                                 keycode = 0x6c; /* break */
  971                         break;
  972                 }
  973         }
  974 
  975         /* return the key code in the K_CODE mode */
  976         if (state->ks_mode == K_CODE) {
  977                 VKBD_UNLOCK(state);
  978                 return (keycode | (scancode & 0x80));
  979         }
  980 
  981         /* compose a character code */
  982         if (state->ks_flags & COMPOSE) {
  983                 switch (keycode | (scancode & 0x80)) {
  984                 /* key pressed, process it */
  985                 case 0x47: case 0x48: case 0x49:        /* keypad 7,8,9 */
  986                         state->ks_composed_char *= 10;
  987                         state->ks_composed_char += keycode - 0x40;
  988                         if (state->ks_composed_char > UCHAR_MAX) {
  989                                 VKBD_UNLOCK(state);
  990                                 return (ERRKEY);
  991                         }
  992                         goto next_code;
  993                 case 0x4B: case 0x4C: case 0x4D:        /* keypad 4,5,6 */
  994                         state->ks_composed_char *= 10;
  995                         state->ks_composed_char += keycode - 0x47;
  996                         if (state->ks_composed_char > UCHAR_MAX) {
  997                                 VKBD_UNLOCK(state);
  998                                 return (ERRKEY);
  999                         }
 1000                         goto next_code;
 1001                 case 0x4F: case 0x50: case 0x51:        /* keypad 1,2,3 */
 1002                         state->ks_composed_char *= 10;
 1003                         state->ks_composed_char += keycode - 0x4E;
 1004                         if (state->ks_composed_char > UCHAR_MAX) {
 1005                                 VKBD_UNLOCK(state);
 1006                                 return (ERRKEY);
 1007                         }
 1008                         goto next_code;
 1009                 case 0x52:      /* keypad 0 */
 1010                         state->ks_composed_char *= 10;
 1011                         if (state->ks_composed_char > UCHAR_MAX) {
 1012                                 VKBD_UNLOCK(state);
 1013                                 return (ERRKEY);
 1014                         }
 1015                         goto next_code;
 1016 
 1017                 /* key released, no interest here */
 1018                 case 0xC7: case 0xC8: case 0xC9:        /* keypad 7,8,9 */
 1019                 case 0xCB: case 0xCC: case 0xCD:        /* keypad 4,5,6 */
 1020                 case 0xCF: case 0xD0: case 0xD1:        /* keypad 1,2,3 */
 1021                 case 0xD2:                              /* keypad 0 */
 1022                         goto next_code;
 1023 
 1024                 case 0x38:                              /* left alt key */
 1025                         break;
 1026 
 1027                 default:
 1028                         if (state->ks_composed_char > 0) {
 1029                                 state->ks_flags &= ~COMPOSE;
 1030                                 state->ks_composed_char = 0;
 1031                                 VKBD_UNLOCK(state);
 1032                                 return (ERRKEY);
 1033                         }
 1034                         break;
 1035                 }
 1036         }
 1037 
 1038         /* keycode to key action */
 1039         action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
 1040                         &state->ks_state, &state->ks_accents);
 1041         if (action == NOKEY)
 1042                 goto next_code;
 1043 
 1044         VKBD_UNLOCK(state);
 1045 
 1046         return (action);
 1047 }
 1048 
 1049 /* Check if char is waiting */
 1050 static int
 1051 vkbd_check_char(keyboard_t *kbd)
 1052 {
 1053         vkbd_state_t    *state = NULL;
 1054         int              ready;
 1055 
 1056         if (!KBD_IS_ACTIVE(kbd))
 1057                 return (FALSE);
 1058 
 1059         state = (vkbd_state_t *) kbd->kb_data;
 1060         
 1061         VKBD_LOCK(state);
 1062         if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0))
 1063                 ready = TRUE;
 1064         else
 1065                 ready = vkbd_data_ready(state);
 1066         VKBD_UNLOCK(state);
 1067 
 1068         return (ready);
 1069 }
 1070 
 1071 /* Some useful control functions (stolen from atkbd.c) */
 1072 static int
 1073 vkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
 1074 {
 1075         vkbd_state_t    *state = (vkbd_state_t *) kbd->kb_data;
 1076         int              i;
 1077 
 1078         VKBD_LOCK(state);
 1079 
 1080         switch (cmd) {
 1081         case KDGKBMODE:         /* get keyboard mode */
 1082                 *(int *)arg = state->ks_mode;
 1083                 break;
 1084 
 1085         case KDSKBMODE:         /* set keyboard mode */
 1086                 switch (*(int *)arg) {
 1087                 case K_XLATE:
 1088                         if (state->ks_mode != K_XLATE) {
 1089                                 /* make lock key state and LED state match */
 1090                                 state->ks_state &= ~LOCK_MASK;
 1091                                 state->ks_state |= KBD_LED_VAL(kbd);
 1092                                 vkbd_status_changed(state);
 1093                         }
 1094                         /* FALLTHROUGH */
 1095 
 1096                 case K_RAW:
 1097                 case K_CODE:
 1098                         if (state->ks_mode != *(int *)arg) {
 1099                                 vkbd_clear_state_locked(state);
 1100                                 state->ks_mode = *(int *)arg;
 1101                                 vkbd_status_changed(state);
 1102                         }
 1103                         break;
 1104 
 1105                 default:
 1106                         VKBD_UNLOCK(state);
 1107                         return (EINVAL);
 1108                 }
 1109                 break;
 1110 
 1111         case KDGETLED:          /* get keyboard LED */
 1112                 *(int *)arg = KBD_LED_VAL(kbd);
 1113                 break;
 1114 
 1115         case KDSETLED:          /* set keyboard LED */
 1116                 /* NOTE: lock key state in ks_state won't be changed */
 1117                 if (*(int *)arg & ~LOCK_MASK) {
 1118                         VKBD_UNLOCK(state);
 1119                         return (EINVAL);
 1120                 }
 1121 
 1122                 i = *(int *)arg;
 1123                 /* replace CAPS LED with ALTGR LED for ALTGR keyboards */
 1124                 if (state->ks_mode == K_XLATE &&
 1125                     kbd->kb_keymap->n_keys > ALTGR_OFFSET) {
 1126                         if (i & ALKED)
 1127                                 i |= CLKED;
 1128                         else
 1129                                 i &= ~CLKED;
 1130                 }
 1131 
 1132                 KBD_LED_VAL(kbd) = *(int *)arg;
 1133                 vkbd_status_changed(state);
 1134                 break;
 1135 
 1136         case KDGKBSTATE:        /* get lock key state */
 1137                 *(int *)arg = state->ks_state & LOCK_MASK;
 1138                 break;
 1139 
 1140         case KDSKBSTATE:        /* set lock key state */
 1141                 if (*(int *)arg & ~LOCK_MASK) {
 1142                         VKBD_UNLOCK(state);
 1143                         return (EINVAL);
 1144                 }
 1145                 state->ks_state &= ~LOCK_MASK;
 1146                 state->ks_state |= *(int *)arg;
 1147                 vkbd_status_changed(state);
 1148                 VKBD_UNLOCK(state);
 1149                 /* set LEDs and quit */
 1150                 return (vkbd_ioctl(kbd, KDSETLED, arg));
 1151 
 1152         case KDSETREPEAT:       /* set keyboard repeat rate (new interface) */
 1153                 i = typematic(((int *)arg)[0], ((int *)arg)[1]);
 1154                 kbd->kb_delay1 = typematic_delay(i);
 1155                 kbd->kb_delay2 = typematic_rate(i);
 1156                 vkbd_status_changed(state);
 1157                 break;
 1158 
 1159         case KDSETRAD:          /* set keyboard repeat rate (old interface) */
 1160                 kbd->kb_delay1 = typematic_delay(*(int *)arg);
 1161                 kbd->kb_delay2 = typematic_rate(*(int *)arg);
 1162                 vkbd_status_changed(state);
 1163                 break;
 1164 
 1165         case PIO_KEYMAP:        /* set keyboard translation table */
 1166         case PIO_KEYMAPENT:     /* set keyboard translation table entry */
 1167         case PIO_DEADKEYMAP:    /* set accent key translation table */
 1168                 state->ks_accents = 0;
 1169                 /* FALLTHROUGH */
 1170 
 1171         default:
 1172                 VKBD_UNLOCK(state);
 1173                 return (genkbd_commonioctl(kbd, cmd, arg));
 1174         }
 1175 
 1176         VKBD_UNLOCK(state);
 1177 
 1178         return (0);
 1179 }
 1180 
 1181 /* Lock the access to the keyboard */
 1182 static int
 1183 vkbd_lock(keyboard_t *kbd, int lock)
 1184 {
 1185         return (1); /* XXX */
 1186 }
 1187 
 1188 /* Clear the internal state of the keyboard */
 1189 static void
 1190 vkbd_clear_state_locked(vkbd_state_t *state)
 1191 {
 1192         VKBD_LOCK_ASSERT(state, MA_OWNED);
 1193 
 1194         state->ks_flags &= ~COMPOSE;
 1195         state->ks_polling = 0;
 1196         state->ks_state &= LOCK_MASK;   /* preserve locking key state */
 1197         state->ks_accents = 0;
 1198         state->ks_composed_char = 0;
 1199 /*      state->ks_prefix = 0;           XXX */
 1200 
 1201         /* flush ks_inq and wakeup writers/poll()ers */
 1202         state->ks_inq.head = state->ks_inq.tail = state->ks_inq.cc = 0;
 1203         selwakeuppri(&state->ks_wsel, PZERO + 1);
 1204         wakeup(&state->ks_inq);
 1205 }
 1206 
 1207 static void
 1208 vkbd_clear_state(keyboard_t *kbd)
 1209 {
 1210         vkbd_state_t    *state = (vkbd_state_t *) kbd->kb_data;
 1211 
 1212         VKBD_LOCK(state);
 1213         vkbd_clear_state_locked(state);
 1214         VKBD_UNLOCK(state);
 1215 }
 1216 
 1217 /* Save the internal state */
 1218 static int
 1219 vkbd_get_state(keyboard_t *kbd, void *buf, size_t len)
 1220 {
 1221         if (len == 0)
 1222                 return (sizeof(vkbd_state_t));
 1223         if (len < sizeof(vkbd_state_t))
 1224                 return (-1);
 1225         bcopy(kbd->kb_data, buf, sizeof(vkbd_state_t)); /* XXX locking? */
 1226         return (0);
 1227 }
 1228 
 1229 /* Set the internal state */
 1230 static int
 1231 vkbd_set_state(keyboard_t *kbd, void *buf, size_t len)
 1232 {
 1233         if (len < sizeof(vkbd_state_t))
 1234                 return (ENOMEM);
 1235         bcopy(buf, kbd->kb_data, sizeof(vkbd_state_t)); /* XXX locking? */
 1236         return (0);
 1237 }
 1238 
 1239 /* Set polling */
 1240 static int
 1241 vkbd_poll(keyboard_t *kbd, int on)
 1242 {
 1243         vkbd_state_t    *state = NULL;
 1244 
 1245         state = (vkbd_state_t *) kbd->kb_data;
 1246 
 1247         VKBD_LOCK(state);
 1248 
 1249         if (on)
 1250                 state->ks_polling ++;
 1251         else
 1252                 state->ks_polling --;
 1253 
 1254         VKBD_UNLOCK(state);
 1255 
 1256         return (0);
 1257 }
 1258 
 1259 /*
 1260  * Local functions
 1261  */
 1262 
 1263 static int delays[] = { 250, 500, 750, 1000 };
 1264 static int rates[] = {  34,  38,  42,  46,  50,  55,  59,  63,
 1265                         68,  76,  84,  92, 100, 110, 118, 126,
 1266                         136, 152, 168, 184, 200, 220, 236, 252,
 1267                         272, 304, 336, 368, 400, 440, 472, 504 };
 1268 
 1269 static int
 1270 typematic_delay(int i)
 1271 {
 1272         return (delays[(i >> 5) & 3]);
 1273 }
 1274 
 1275 static int
 1276 typematic_rate(int i)
 1277 {
 1278         return (rates[i & 0x1f]);
 1279 }
 1280 
 1281 static int
 1282 typematic(int delay, int rate)
 1283 {
 1284         int value;
 1285         int i;
 1286 
 1287         for (i = sizeof(delays)/sizeof(delays[0]) - 1; i > 0; i --) {
 1288                 if (delay >= delays[i])
 1289                         break;
 1290         }
 1291         value = i << 5;
 1292         for (i = sizeof(rates)/sizeof(rates[0]) - 1; i > 0; i --) {
 1293                 if (rate >= rates[i])
 1294                         break;
 1295         }
 1296         value |= i;
 1297         return (value);
 1298 }
 1299 
 1300 /*****************************************************************************
 1301  *****************************************************************************
 1302  **                                    Module 
 1303  *****************************************************************************
 1304  *****************************************************************************/
 1305 
 1306 KEYBOARD_DRIVER(vkbd, vkbdsw, vkbd_configure);
 1307 
 1308 static int
 1309 vkbd_modevent(module_t mod, int type, void *data)
 1310 {
 1311         static eventhandler_tag tag;
 1312 
 1313         switch (type) {
 1314         case MOD_LOAD:
 1315                 clone_setup(&vkbd_dev_clones);
 1316                 tag = EVENTHANDLER_REGISTER(dev_clone, vkbd_dev_clone, 0, 1000);
 1317                 if (tag == NULL) {
 1318                         clone_cleanup(&vkbd_dev_clones);
 1319                         return (ENOMEM);
 1320                 }
 1321                 kbd_add_driver(&vkbd_kbd_driver);
 1322                 break;
 1323 
 1324         case MOD_UNLOAD:
 1325                 kbd_delete_driver(&vkbd_kbd_driver);
 1326                 EVENTHANDLER_DEREGISTER(dev_clone, tag);
 1327                 clone_cleanup(&vkbd_dev_clones);
 1328                 break;
 1329 
 1330         default:
 1331                 return (EOPNOTSUPP);
 1332         }
 1333 
 1334         return (0);
 1335 }
 1336 
 1337 DEV_MODULE(vkbd, vkbd_modevent, NULL);
 1338 

Cache object: 6cd76e19e74a85e1089047eb540ab292


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