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