]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/vkbd/vkbd.c
MFV r360158:
[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/eventhandler.h>
41 #include <sys/fcntl.h>
42 #include <sys/kbio.h>
43 #include <sys/kernel.h>
44 #include <sys/limits.h>
45 #include <sys/lock.h>
46 #include <sys/malloc.h>
47 #include <sys/module.h>
48 #include <sys/mutex.h>
49 #include <sys/poll.h>
50 #include <sys/proc.h>
51 #include <sys/queue.h>
52 #include <sys/selinfo.h>
53 #include <sys/systm.h>
54 #include <sys/taskqueue.h>
55 #include <sys/uio.h>
56 #include <dev/kbd/kbdreg.h>
57 #include <dev/kbd/kbdtables.h>
58 #include <dev/vkbd/vkbd_var.h>
59
60 #define DEVICE_NAME     "vkbdctl"
61 #define KEYBOARD_NAME   "vkbd"
62
63 MALLOC_DECLARE(M_VKBD);
64 MALLOC_DEFINE(M_VKBD, KEYBOARD_NAME, "Virtual AT keyboard");
65
66 /*****************************************************************************
67  *****************************************************************************
68  **                             Keyboard state
69  *****************************************************************************
70  *****************************************************************************/
71
72 /*
73  * XXX
74  * For now rely on Giant mutex to protect our data structures.
75  * Just like the rest of keyboard drivers and syscons(4) do.
76  */
77
78 #if 0 /* not yet */
79 #define VKBD_LOCK_DECL          struct mtx ks_lock
80 #define VKBD_LOCK_INIT(s)       mtx_init(&(s)->ks_lock, "vkbd_lock", NULL, MTX_DEF|MTX_RECURSE)
81 #define VKBD_LOCK_DESTROY(s)    mtx_destroy(&(s)->ks_lock)
82 #define VKBD_LOCK(s)            mtx_lock(&(s)->ks_lock)
83 #define VKBD_UNLOCK(s)          mtx_unlock(&(s)->ks_lock)
84 #define VKBD_LOCK_ASSERT(s, w)  mtx_assert(&(s)->ks_lock, w)
85 #define VKBD_SLEEP(s, f, d, t) \
86         msleep(&(s)->f, &(s)->ks_lock, PCATCH | (PZERO + 1), d, t)
87 #else
88 #define VKBD_LOCK_DECL
89 #define VKBD_LOCK_INIT(s)
90 #define VKBD_LOCK_DESTROY(s)
91 #define VKBD_LOCK(s)
92 #define VKBD_UNLOCK(s)
93 #define VKBD_LOCK_ASSERT(s, w)
94 #define VKBD_SLEEP(s, f, d, t)  tsleep(&(s)->f, PCATCH | (PZERO + 1), d, t)
95 #endif
96
97 #define VKBD_KEYBOARD(d) \
98         kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, dev2unit(d)))
99
100 /* vkbd queue */
101 struct vkbd_queue
102 {
103         int             q[VKBD_Q_SIZE]; /* queue */
104         int             head;           /* index of the first code */
105         int             tail;           /* index of the last code */
106         int             cc;             /* number of codes in queue */
107 };
108
109 typedef struct vkbd_queue       vkbd_queue_t;
110
111 /* vkbd state */
112 struct vkbd_state
113 {
114         struct cdev     *ks_dev;        /* control device */
115
116         struct selinfo   ks_rsel;       /* select(2) */
117         struct selinfo   ks_wsel;
118
119         vkbd_queue_t     ks_inq;        /* input key codes queue */
120         struct task      ks_task;       /* interrupt task */
121
122         int              ks_flags;      /* flags */
123 #define OPEN            (1 << 0)        /* control device is open */
124 #define COMPOSE         (1 << 1)        /* compose flag */
125 #define STATUS          (1 << 2)        /* status has changed */
126 #define TASK            (1 << 3)        /* interrupt task queued */
127 #define READ            (1 << 4)        /* read pending */
128 #define WRITE           (1 << 5)        /* write pending */
129
130         int              ks_mode;       /* K_XLATE, K_RAW, K_CODE */
131         int              ks_polling;    /* polling flag */
132         int              ks_state;      /* shift/lock key state */
133         int              ks_accents;    /* accent key index (> 0) */
134         u_int            ks_composed_char; /* composed char code */
135         u_char           ks_prefix;     /* AT scan code prefix */
136
137         VKBD_LOCK_DECL;
138 };
139
140 typedef struct vkbd_state       vkbd_state_t;
141
142 /*****************************************************************************
143  *****************************************************************************
144  **                             Character device
145  *****************************************************************************
146  *****************************************************************************/
147
148 static void             vkbd_dev_clone(void *, struct ucred *, char *, int,
149                             struct cdev **);
150 static d_open_t         vkbd_dev_open;
151 static d_close_t        vkbd_dev_close;
152 static d_read_t         vkbd_dev_read;
153 static d_write_t        vkbd_dev_write;
154 static d_ioctl_t        vkbd_dev_ioctl;
155 static d_poll_t         vkbd_dev_poll;
156 static void             vkbd_dev_intr(void *, int);
157 static void             vkbd_status_changed(vkbd_state_t *);
158 static int              vkbd_data_ready(vkbd_state_t *);
159 static int              vkbd_data_read(vkbd_state_t *, int);
160
161 static struct cdevsw    vkbd_dev_cdevsw = {
162         .d_version =    D_VERSION,
163         .d_flags =      D_NEEDGIANT | D_NEEDMINOR,
164         .d_open =       vkbd_dev_open,
165         .d_close =      vkbd_dev_close,
166         .d_read =       vkbd_dev_read,
167         .d_write =      vkbd_dev_write,
168         .d_ioctl =      vkbd_dev_ioctl,
169         .d_poll =       vkbd_dev_poll,
170         .d_name =       DEVICE_NAME,
171 };
172
173 static struct clonedevs *vkbd_dev_clones = NULL;
174
175 /* Clone device */
176 static void
177 vkbd_dev_clone(void *arg, struct ucred *cred, char *name, int namelen,
178     struct cdev **dev)
179 {
180         int     unit;
181
182         if (*dev != NULL)
183                 return;
184
185         if (strcmp(name, DEVICE_NAME) == 0)
186                 unit = -1;
187         else if (dev_stdclone(name, NULL, DEVICE_NAME, &unit) != 1)
188                 return; /* don't recognize the name */
189
190         /* find any existing device, or allocate new unit number */
191         if (clone_create(&vkbd_dev_clones, &vkbd_dev_cdevsw, &unit, dev, 0))
192                 *dev = make_dev_credf(MAKEDEV_REF, &vkbd_dev_cdevsw, unit,
193                         cred, UID_ROOT, GID_WHEEL, 0600, DEVICE_NAME "%d",
194                         unit);
195 }
196
197 /* Open device */
198 static int
199 vkbd_dev_open(struct cdev *dev, int flag, int mode, struct thread *td)
200 {
201         int                      unit = dev2unit(dev), error;
202         keyboard_switch_t       *sw = NULL;
203         keyboard_t              *kbd = NULL;
204         vkbd_state_t            *state = (vkbd_state_t *) dev->si_drv1;
205
206         /* XXX FIXME: dev->si_drv1 locking */
207         if (state == NULL) {
208                 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL)
209                         return (ENXIO);
210
211                 if ((error = (*sw->probe)(unit, NULL, 0)) != 0 ||
212                     (error = (*sw->init)(unit, &kbd, NULL, 0)) != 0)
213                         return (error);
214
215                 state = (vkbd_state_t *) kbd->kb_data;
216
217                 if ((error = (*sw->enable)(kbd)) != 0) {
218                         (*sw->term)(kbd);
219                         return (error);
220                 }
221
222 #ifdef KBD_INSTALL_CDEV
223                 if ((error = kbd_attach(kbd)) != 0) {
224                         (*sw->disable)(kbd);
225                         (*sw->term)(kbd);
226                         return (error);
227                 }
228 #endif /* def KBD_INSTALL_CDEV */
229
230                 dev->si_drv1 = kbd->kb_data;
231         }
232
233         VKBD_LOCK(state);
234
235         if (state->ks_flags & OPEN) {
236                 VKBD_UNLOCK(state);
237                 return (EBUSY);
238         }
239
240         state->ks_flags |= OPEN;
241         state->ks_dev = dev;
242
243         VKBD_UNLOCK(state);
244
245         return (0);
246 }
247
248 /* Close device */
249 static int
250 vkbd_dev_close(struct cdev *dev, int foo, int bar, struct thread *td)
251 {
252         keyboard_t      *kbd = VKBD_KEYBOARD(dev);
253         vkbd_state_t    *state = NULL;
254
255         if (kbd == NULL)
256                 return (ENXIO);
257
258         if (kbd->kb_data == NULL || kbd->kb_data != dev->si_drv1)
259                 panic("%s: kbd->kb_data != dev->si_drv1\n", __func__);
260
261         state = (vkbd_state_t *) kbd->kb_data;
262
263         VKBD_LOCK(state);
264
265         /* wait for interrupt task */
266         while (state->ks_flags & TASK)
267                 VKBD_SLEEP(state, ks_task, "vkbdc", 0);
268
269         /* wakeup poll()ers */
270         selwakeuppri(&state->ks_rsel, PZERO + 1);
271         selwakeuppri(&state->ks_wsel, PZERO + 1);
272
273         state->ks_flags &= ~OPEN;
274         state->ks_dev = NULL;
275         state->ks_inq.head = state->ks_inq.tail = state->ks_inq.cc = 0;
276
277         VKBD_UNLOCK(state);
278
279         kbdd_disable(kbd);
280 #ifdef KBD_INSTALL_CDEV
281         kbd_detach(kbd);
282 #endif /* def KBD_INSTALL_CDEV */
283         kbdd_term(kbd);
284
285         /* XXX FIXME: dev->si_drv1 locking */
286         dev->si_drv1 = NULL;
287
288         return (0);
289 }
290
291 /* Read status */
292 static int
293 vkbd_dev_read(struct cdev *dev, struct uio *uio, int flag)
294 {
295         keyboard_t      *kbd = VKBD_KEYBOARD(dev);
296         vkbd_state_t    *state = NULL;
297         vkbd_status_t    status;
298         int              error;
299
300         if (kbd == NULL)
301                 return (ENXIO);
302
303         if (uio->uio_resid != sizeof(status))
304                 return (EINVAL);
305
306         if (kbd->kb_data == NULL || kbd->kb_data != dev->si_drv1)
307                 panic("%s: kbd->kb_data != dev->si_drv1\n", __func__);
308
309         state = (vkbd_state_t *) kbd->kb_data;
310
311         VKBD_LOCK(state);
312
313         if (state->ks_flags & READ) {
314                 VKBD_UNLOCK(state);
315                 return (EALREADY);
316         }
317
318         state->ks_flags |= READ;
319 again:
320         if (state->ks_flags & STATUS) {
321                 state->ks_flags &= ~STATUS;
322
323                 status.mode = state->ks_mode;
324                 status.leds = KBD_LED_VAL(kbd);
325                 status.lock = state->ks_state & LOCK_MASK;
326                 status.delay = kbd->kb_delay1;
327                 status.rate = kbd->kb_delay2;
328                 bzero(status.reserved, sizeof(status.reserved));
329
330                 error = uiomove(&status, sizeof(status), uio);
331         } else {
332                 if (flag & O_NONBLOCK) {
333                         error = EWOULDBLOCK;
334                         goto done;
335                 }
336
337                 error = VKBD_SLEEP(state, ks_flags, "vkbdr", 0);
338                 if (error != 0) 
339                         goto done;
340
341                 goto again;
342         }
343 done:
344         state->ks_flags &= ~READ;
345
346         VKBD_UNLOCK(state);
347         
348         return (error);
349 }
350
351 /* Write scancodes */
352 static int
353 vkbd_dev_write(struct cdev *dev, struct uio *uio, int flag)
354 {
355         keyboard_t      *kbd = VKBD_KEYBOARD(dev);
356         vkbd_state_t    *state = NULL;
357         vkbd_queue_t    *q = NULL;
358         int              error, avail, bytes;
359
360         if (kbd == NULL)
361                 return (ENXIO);
362
363         if (uio->uio_resid <= 0)
364                 return (EINVAL);
365
366         if (kbd->kb_data == NULL || kbd->kb_data != dev->si_drv1)
367                 panic("%s: kbd->kb_data != dev->si_drv1\n", __func__);
368
369         state = (vkbd_state_t *) kbd->kb_data;
370
371         VKBD_LOCK(state);
372
373         if (state->ks_flags & WRITE) {
374                 VKBD_UNLOCK(state);
375                 return (EALREADY);
376         }
377
378         state->ks_flags |= WRITE;
379         error = 0;
380         q = &state->ks_inq;
381
382         while (uio->uio_resid >= sizeof(q->q[0])) {
383                 if (q->head == q->tail) {
384                         if (q->cc == 0)
385                                 avail = nitems(q->q) - q->head;
386                         else
387                                 avail = 0; /* queue must be full */
388                 } else if (q->head < q->tail)
389                         avail = nitems(q->q) - q->tail;
390                 else
391                         avail = q->head - q->tail;
392
393                 if (avail == 0) {
394                         if (flag & O_NONBLOCK) {
395                                 error = EWOULDBLOCK;
396                                 break;
397                         }
398
399                         error = VKBD_SLEEP(state, ks_inq, "vkbdw", 0);
400                         if (error != 0)
401                                 break;
402                 } else {
403                         bytes = avail * sizeof(q->q[0]);
404                         if (bytes > uio->uio_resid) {
405                                 avail = uio->uio_resid / sizeof(q->q[0]);
406                                 bytes = avail * sizeof(q->q[0]);
407                         }
408
409                         error = uiomove((void *) &q->q[q->tail], bytes, uio);
410                         if (error != 0)
411                                 break;
412
413                         q->cc += avail;
414                         q->tail += avail;
415                         if (q->tail == nitems(q->q))
416                                 q->tail = 0;
417
418                         /* queue interrupt task if needed */
419                         if (!(state->ks_flags & TASK) &&
420                             taskqueue_enqueue(taskqueue_swi_giant, &state->ks_task) == 0)
421                                 state->ks_flags |= TASK;
422                 }
423         }
424
425         state->ks_flags &= ~WRITE;
426
427         VKBD_UNLOCK(state);
428
429         return (error);
430 }
431
432 /* Process ioctl */
433 static int
434 vkbd_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
435 {
436         keyboard_t      *kbd = VKBD_KEYBOARD(dev);
437
438         return ((kbd == NULL)? ENXIO : kbdd_ioctl(kbd, cmd, data));
439 }
440
441 /* Poll device */
442 static int
443 vkbd_dev_poll(struct cdev *dev, int events, struct thread *td)
444 {
445         vkbd_state_t    *state = (vkbd_state_t *) dev->si_drv1;
446         vkbd_queue_t    *q = NULL;
447         int              revents = 0;
448
449         if (state == NULL)
450                 return (ENXIO);
451
452         VKBD_LOCK(state);
453
454         q = &state->ks_inq;
455
456         if (events & (POLLIN | POLLRDNORM)) {
457                 if (state->ks_flags & STATUS)
458                         revents |= events & (POLLIN | POLLRDNORM);
459                 else
460                         selrecord(td, &state->ks_rsel);
461         }
462
463         if (events & (POLLOUT | POLLWRNORM)) {
464                 if (q->cc < nitems(q->q))
465                         revents |= events & (POLLOUT | POLLWRNORM);
466                 else
467                         selrecord(td, &state->ks_wsel);
468         }
469
470         VKBD_UNLOCK(state);
471
472         return (revents);
473 }
474
475 /* Interrupt handler */
476 void
477 vkbd_dev_intr(void *xkbd, int pending)
478 {
479         keyboard_t      *kbd = (keyboard_t *) xkbd;
480         vkbd_state_t    *state = (vkbd_state_t *) kbd->kb_data;
481
482         kbdd_intr(kbd, NULL);
483
484         VKBD_LOCK(state);
485
486         state->ks_flags &= ~TASK;
487         wakeup(&state->ks_task);
488
489         VKBD_UNLOCK(state);
490 }
491
492 /* Set status change flags */
493 static void
494 vkbd_status_changed(vkbd_state_t *state)
495 {
496         VKBD_LOCK_ASSERT(state, MA_OWNED);
497
498         if (!(state->ks_flags & STATUS)) {
499                 state->ks_flags |= STATUS;
500                 selwakeuppri(&state->ks_rsel, PZERO + 1);
501                 wakeup(&state->ks_flags);
502         }
503 }
504
505 /* Check if we have data in the input queue */
506 static int
507 vkbd_data_ready(vkbd_state_t *state)
508 {
509         VKBD_LOCK_ASSERT(state, MA_OWNED);
510
511         return (state->ks_inq.cc > 0);
512 }
513
514 /* Read one code from the input queue */
515 static int
516 vkbd_data_read(vkbd_state_t *state, int wait)
517 {
518         vkbd_queue_t    *q = &state->ks_inq;
519         int              c;
520
521         VKBD_LOCK_ASSERT(state, MA_OWNED);
522
523         if (q->cc == 0)
524                 return (-1);
525
526         /* get first code from the queue */
527         q->cc --;
528         c = q->q[q->head ++];
529         if (q->head == nitems(q->q))
530                 q->head = 0;
531
532         /* wakeup ks_inq writers/poll()ers */
533         selwakeuppri(&state->ks_wsel, PZERO + 1);
534         wakeup(q);
535
536         return (c);
537 }
538
539 /****************************************************************************
540  ****************************************************************************
541  **                              Keyboard driver
542  ****************************************************************************
543  ****************************************************************************/
544
545 static int              vkbd_configure(int flags);
546 static kbd_probe_t      vkbd_probe;
547 static kbd_init_t       vkbd_init;
548 static kbd_term_t       vkbd_term;
549 static kbd_intr_t       vkbd_intr;
550 static kbd_test_if_t    vkbd_test_if;
551 static kbd_enable_t     vkbd_enable;
552 static kbd_disable_t    vkbd_disable;
553 static kbd_read_t       vkbd_read;
554 static kbd_check_t      vkbd_check;
555 static kbd_read_char_t  vkbd_read_char;
556 static kbd_check_char_t vkbd_check_char;
557 static kbd_ioctl_t      vkbd_ioctl;
558 static kbd_lock_t       vkbd_lock;
559 static void             vkbd_clear_state_locked(vkbd_state_t *state);
560 static kbd_clear_state_t vkbd_clear_state;
561 static kbd_get_state_t  vkbd_get_state;
562 static kbd_set_state_t  vkbd_set_state;
563 static kbd_poll_mode_t  vkbd_poll;
564
565 static keyboard_switch_t vkbdsw = {
566         .probe =        vkbd_probe,
567         .init =         vkbd_init,
568         .term =         vkbd_term,
569         .intr =         vkbd_intr,
570         .test_if =      vkbd_test_if,
571         .enable =       vkbd_enable,
572         .disable =      vkbd_disable,
573         .read =         vkbd_read,
574         .check =        vkbd_check,
575         .read_char =    vkbd_read_char,
576         .check_char =   vkbd_check_char,
577         .ioctl =        vkbd_ioctl,
578         .lock =         vkbd_lock,
579         .clear_state =  vkbd_clear_state,
580         .get_state =    vkbd_get_state,
581         .set_state =    vkbd_set_state,
582         .poll =         vkbd_poll,
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 = nitems(delays) - 1; i > 0; i --) {
1330                 if (delay >= delays[i])
1331                         break;
1332         }
1333         value = i << 5;
1334         for (i = nitems(rates) - 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