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