]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/vkbd/vkbd.c
MFV r349454:
[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         .get_fkeystr =  genkbd_get_fkeystr,
583         .poll =         vkbd_poll,
584         .diag =         genkbd_diag,
585 };
586
587 static int      typematic(int delay, int rate);
588 static int      typematic_delay(int delay);
589 static int      typematic_rate(int rate);
590
591 /* Return the number of found keyboards */
592 static int
593 vkbd_configure(int flags)
594 {
595         return (1);
596 }
597
598 /* Detect a keyboard */
599 static int
600 vkbd_probe(int unit, void *arg, int flags)
601 {
602         return (0);
603 }
604
605 /* Reset and initialize the keyboard (stolen from atkbd.c) */
606 static int
607 vkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
608 {
609         keyboard_t      *kbd = NULL;
610         vkbd_state_t    *state = NULL;
611         keymap_t        *keymap = NULL;
612         accentmap_t     *accmap = NULL;
613         fkeytab_t       *fkeymap = NULL;
614         int              fkeymap_size, delay[2];
615         int              error, needfree;
616
617         if (*kbdp == NULL) {
618                 *kbdp = kbd = malloc(sizeof(*kbd), M_VKBD, M_NOWAIT | M_ZERO);
619                 state = malloc(sizeof(*state), M_VKBD, M_NOWAIT | M_ZERO);
620                 keymap = malloc(sizeof(key_map), M_VKBD, M_NOWAIT);
621                 accmap = malloc(sizeof(accent_map), M_VKBD, M_NOWAIT);
622                 fkeymap = malloc(sizeof(fkey_tab), M_VKBD, M_NOWAIT);
623                 fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
624                 needfree = 1;
625                 if ((kbd == NULL) || (state == NULL) || (keymap == NULL) ||
626                     (accmap == NULL) || (fkeymap == NULL)) {
627                         error = ENOMEM;
628                         goto bad;
629                 }
630
631                 VKBD_LOCK_INIT(state);
632                 state->ks_inq.head = state->ks_inq.tail = state->ks_inq.cc = 0;
633                 TASK_INIT(&state->ks_task, 0, vkbd_dev_intr, (void *) kbd);
634         } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
635                 return (0);
636         } else {
637                 kbd = *kbdp;
638                 state = (vkbd_state_t *) kbd->kb_data;
639                 keymap = kbd->kb_keymap;
640                 accmap = kbd->kb_accentmap;
641                 fkeymap = kbd->kb_fkeytab;
642                 fkeymap_size = kbd->kb_fkeytab_size;
643                 needfree = 0;
644         }
645
646         if (!KBD_IS_PROBED(kbd)) {
647                 kbd_init_struct(kbd, KEYBOARD_NAME, KB_OTHER, unit, flags, 0, 0);
648                 bcopy(&key_map, keymap, sizeof(key_map));
649                 bcopy(&accent_map, accmap, sizeof(accent_map));
650                 bcopy(fkey_tab, fkeymap,
651                         imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
652                 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
653                 kbd->kb_data = (void *)state;
654         
655                 KBD_FOUND_DEVICE(kbd);
656                 KBD_PROBE_DONE(kbd);
657
658                 VKBD_LOCK(state);
659                 vkbd_clear_state_locked(state);
660                 state->ks_mode = K_XLATE;
661                 /* FIXME: set the initial value for lock keys in ks_state */
662                 VKBD_UNLOCK(state);
663         }
664         if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
665                 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
666
667                 vkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
668                 delay[0] = kbd->kb_delay1;
669                 delay[1] = kbd->kb_delay2;
670                 vkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
671
672                 KBD_INIT_DONE(kbd);
673         }
674         if (!KBD_IS_CONFIGURED(kbd)) {
675                 if (kbd_register(kbd) < 0) {
676                         error = ENXIO;
677                         goto bad;
678                 }
679                 KBD_CONFIG_DONE(kbd);
680         }
681
682         return (0);
683 bad:
684         if (needfree) {
685                 if (state != NULL)
686                         free(state, M_VKBD);
687                 if (keymap != NULL)
688                         free(keymap, M_VKBD);
689                 if (accmap != NULL)
690                         free(accmap, M_VKBD);
691                 if (fkeymap != NULL)
692                         free(fkeymap, M_VKBD);
693                 if (kbd != NULL) {
694                         free(kbd, M_VKBD);
695                         *kbdp = NULL;   /* insure ref doesn't leak to caller */
696                 }
697         }
698         return (error);
699 }
700
701 /* Finish using this keyboard */
702 static int
703 vkbd_term(keyboard_t *kbd)
704 {
705         vkbd_state_t    *state = (vkbd_state_t *) kbd->kb_data;
706
707         kbd_unregister(kbd);
708
709         VKBD_LOCK_DESTROY(state);
710         bzero(state, sizeof(*state));
711         free(state, M_VKBD);
712
713         free(kbd->kb_keymap, M_VKBD);
714         free(kbd->kb_accentmap, M_VKBD);
715         free(kbd->kb_fkeytab, M_VKBD);
716         free(kbd, M_VKBD);
717
718         return (0);
719 }
720
721 /* Keyboard interrupt routine */
722 static int
723 vkbd_intr(keyboard_t *kbd, void *arg)
724 {
725         int     c;
726
727         if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
728                 /* let the callback function to process the input */
729                 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
730                                             kbd->kb_callback.kc_arg);
731         } else {
732                 /* read and discard the input; no one is waiting for input */
733                 do {
734                         c = vkbd_read_char(kbd, FALSE);
735                 } while (c != NOKEY);
736         }
737
738         return (0);
739 }
740
741 /* Test the interface to the device */
742 static int
743 vkbd_test_if(keyboard_t *kbd)
744 {
745         return (0);
746 }
747
748 /* 
749  * Enable the access to the device; until this function is called,
750  * the client cannot read from the keyboard.
751  */
752
753 static int
754 vkbd_enable(keyboard_t *kbd)
755 {
756         KBD_ACTIVATE(kbd);
757         return (0);
758 }
759
760 /* Disallow the access to the device */
761 static int
762 vkbd_disable(keyboard_t *kbd)
763 {
764         KBD_DEACTIVATE(kbd);
765         return (0);
766 }
767
768 /* Read one byte from the keyboard if it's allowed */
769 static int
770 vkbd_read(keyboard_t *kbd, int wait)
771 {
772         vkbd_state_t    *state = (vkbd_state_t *) kbd->kb_data;
773         int              c;
774
775         VKBD_LOCK(state);
776         c = vkbd_data_read(state, wait);
777         VKBD_UNLOCK(state);
778
779         if (c != -1)
780                 kbd->kb_count ++;
781
782         return (KBD_IS_ACTIVE(kbd)? c : -1);
783 }
784
785 /* Check if data is waiting */
786 static int
787 vkbd_check(keyboard_t *kbd)
788 {
789         vkbd_state_t    *state = NULL;
790         int              ready;
791
792         if (!KBD_IS_ACTIVE(kbd))
793                 return (FALSE);
794
795         state = (vkbd_state_t *) kbd->kb_data;
796
797         VKBD_LOCK(state);
798         ready = vkbd_data_ready(state);
799         VKBD_UNLOCK(state);
800
801         return (ready);
802 }
803
804 /* Read char from the keyboard (stolen from atkbd.c) */
805 static u_int
806 vkbd_read_char(keyboard_t *kbd, int wait)
807 {
808         vkbd_state_t    *state = (vkbd_state_t *) kbd->kb_data;
809         u_int            action;
810         int              scancode, keycode;
811
812         VKBD_LOCK(state);
813
814 next_code:
815
816         /* do we have a composed char to return? */
817         if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
818                 action = state->ks_composed_char;
819                 state->ks_composed_char = 0;
820                 if (action > UCHAR_MAX) {
821                         VKBD_UNLOCK(state);
822                         return (ERRKEY);
823                 }
824
825                 VKBD_UNLOCK(state);
826                 return (action);
827         }
828
829         /* see if there is something in the keyboard port */
830         scancode = vkbd_data_read(state, wait);
831         if (scancode == -1) {
832                 VKBD_UNLOCK(state);
833                 return (NOKEY);
834         }
835         /* XXX FIXME: check for -1 if wait == 1! */
836
837         kbd->kb_count ++;
838
839         /* return the byte as is for the K_RAW mode */
840         if (state->ks_mode == K_RAW) {
841                 VKBD_UNLOCK(state);
842                 return (scancode);
843         }
844
845         /* translate the scan code into a keycode */
846         keycode = scancode & 0x7F;
847         switch (state->ks_prefix) {
848         case 0x00:      /* normal scancode */
849                 switch(scancode) {
850                 case 0xB8:      /* left alt (compose key) released */
851                         if (state->ks_flags & COMPOSE) {
852                                 state->ks_flags &= ~COMPOSE;
853                                 if (state->ks_composed_char > UCHAR_MAX)
854                                         state->ks_composed_char = 0;
855                         }
856                         break;
857                 case 0x38:      /* left alt (compose key) pressed */
858                         if (!(state->ks_flags & COMPOSE)) {
859                                 state->ks_flags |= COMPOSE;
860                                 state->ks_composed_char = 0;
861                         }
862                         break;
863                 case 0xE0:
864                 case 0xE1:
865                         state->ks_prefix = scancode;
866                         goto next_code;
867                 }
868                 break;
869         case 0xE0:      /* 0xE0 prefix */
870                 state->ks_prefix = 0;
871                 switch (keycode) {
872                 case 0x1C:      /* right enter key */
873                         keycode = 0x59;
874                         break;
875                 case 0x1D:      /* right ctrl key */
876                         keycode = 0x5A;
877                         break;
878                 case 0x35:      /* keypad divide key */
879                         keycode = 0x5B;
880                         break;
881                 case 0x37:      /* print scrn key */
882                         keycode = 0x5C;
883                         break;
884                 case 0x38:      /* right alt key (alt gr) */
885                         keycode = 0x5D;
886                         break;
887                 case 0x46:      /* ctrl-pause/break on AT 101 (see below) */
888                         keycode = 0x68;
889                         break;
890                 case 0x47:      /* grey home key */
891                         keycode = 0x5E;
892                         break;
893                 case 0x48:      /* grey up arrow key */
894                         keycode = 0x5F;
895                         break;
896                 case 0x49:      /* grey page up key */
897                         keycode = 0x60;
898                         break;
899                 case 0x4B:      /* grey left arrow key */
900                         keycode = 0x61;
901                         break;
902                 case 0x4D:      /* grey right arrow key */
903                         keycode = 0x62;
904                         break;
905                 case 0x4F:      /* grey end key */
906                         keycode = 0x63;
907                         break;
908                 case 0x50:      /* grey down arrow key */
909                         keycode = 0x64;
910                         break;
911                 case 0x51:      /* grey page down key */
912                         keycode = 0x65;
913                         break;
914                 case 0x52:      /* grey insert key */
915                         keycode = 0x66;
916                         break;
917                 case 0x53:      /* grey delete key */
918                         keycode = 0x67;
919                         break;
920                 /* the following 3 are only used on the MS "Natural" keyboard */
921                 case 0x5b:      /* left Window key */
922                         keycode = 0x69;
923                         break;
924                 case 0x5c:      /* right Window key */
925                         keycode = 0x6a;
926                         break;
927                 case 0x5d:      /* menu key */
928                         keycode = 0x6b;
929                         break;
930                 case 0x5e:      /* power key */
931                         keycode = 0x6d;
932                         break;
933                 case 0x5f:      /* sleep key */
934                         keycode = 0x6e;
935                         break;
936                 case 0x63:      /* wake key */
937                         keycode = 0x6f;
938                         break;
939                 default:        /* ignore everything else */
940                         goto next_code;
941                 }
942                 break;
943         case 0xE1:      /* 0xE1 prefix */
944                 /* 
945                  * The pause/break key on the 101 keyboard produces:
946                  * E1-1D-45 E1-9D-C5
947                  * Ctrl-pause/break produces:
948                  * E0-46 E0-C6 (See above.)
949                  */
950                 state->ks_prefix = 0;
951                 if (keycode == 0x1D)
952                         state->ks_prefix = 0x1D;
953                 goto next_code;
954                 /* NOT REACHED */
955         case 0x1D:      /* pause / break */
956                 state->ks_prefix = 0;
957                 if (keycode != 0x45)
958                         goto next_code;
959                 keycode = 0x68;
960                 break;
961         }
962
963         if (kbd->kb_type == KB_84) {
964                 switch (keycode) {
965                 case 0x37:      /* *(numpad)/print screen */
966                         if (state->ks_flags & SHIFTS)
967                                 keycode = 0x5c; /* print screen */
968                         break;
969                 case 0x45:      /* num lock/pause */
970                         if (state->ks_flags & CTLS)
971                                 keycode = 0x68; /* pause */
972                         break;
973                 case 0x46:      /* scroll lock/break */
974                         if (state->ks_flags & CTLS)
975                                 keycode = 0x6c; /* break */
976                         break;
977                 }
978         } else if (kbd->kb_type == KB_101) {
979                 switch (keycode) {
980                 case 0x5c:      /* print screen */
981                         if (state->ks_flags & ALTS)
982                                 keycode = 0x54; /* sysrq */
983                         break;
984                 case 0x68:      /* pause/break */
985                         if (state->ks_flags & CTLS)
986                                 keycode = 0x6c; /* break */
987                         break;
988                 }
989         }
990
991         /* return the key code in the K_CODE mode */
992         if (state->ks_mode == K_CODE) {
993                 VKBD_UNLOCK(state);
994                 return (keycode | (scancode & 0x80));
995         }
996
997         /* compose a character code */
998         if (state->ks_flags & COMPOSE) {
999                 switch (keycode | (scancode & 0x80)) {
1000                 /* key pressed, process it */
1001                 case 0x47: case 0x48: case 0x49:        /* keypad 7,8,9 */
1002                         state->ks_composed_char *= 10;
1003                         state->ks_composed_char += keycode - 0x40;
1004                         if (state->ks_composed_char > UCHAR_MAX) {
1005                                 VKBD_UNLOCK(state);
1006                                 return (ERRKEY);
1007                         }
1008                         goto next_code;
1009                 case 0x4B: case 0x4C: case 0x4D:        /* keypad 4,5,6 */
1010                         state->ks_composed_char *= 10;
1011                         state->ks_composed_char += keycode - 0x47;
1012                         if (state->ks_composed_char > UCHAR_MAX) {
1013                                 VKBD_UNLOCK(state);
1014                                 return (ERRKEY);
1015                         }
1016                         goto next_code;
1017                 case 0x4F: case 0x50: case 0x51:        /* keypad 1,2,3 */
1018                         state->ks_composed_char *= 10;
1019                         state->ks_composed_char += keycode - 0x4E;
1020                         if (state->ks_composed_char > UCHAR_MAX) {
1021                                 VKBD_UNLOCK(state);
1022                                 return (ERRKEY);
1023                         }
1024                         goto next_code;
1025                 case 0x52:      /* keypad 0 */
1026                         state->ks_composed_char *= 10;
1027                         if (state->ks_composed_char > UCHAR_MAX) {
1028                                 VKBD_UNLOCK(state);
1029                                 return (ERRKEY);
1030                         }
1031                         goto next_code;
1032
1033                 /* key released, no interest here */
1034                 case 0xC7: case 0xC8: case 0xC9:        /* keypad 7,8,9 */
1035                 case 0xCB: case 0xCC: case 0xCD:        /* keypad 4,5,6 */
1036                 case 0xCF: case 0xD0: case 0xD1:        /* keypad 1,2,3 */
1037                 case 0xD2:                              /* keypad 0 */
1038                         goto next_code;
1039
1040                 case 0x38:                              /* left alt key */
1041                         break;
1042
1043                 default:
1044                         if (state->ks_composed_char > 0) {
1045                                 state->ks_flags &= ~COMPOSE;
1046                                 state->ks_composed_char = 0;
1047                                 VKBD_UNLOCK(state);
1048                                 return (ERRKEY);
1049                         }
1050                         break;
1051                 }
1052         }
1053
1054         /* keycode to key action */
1055         action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
1056                         &state->ks_state, &state->ks_accents);
1057         if (action == NOKEY)
1058                 goto next_code;
1059
1060         VKBD_UNLOCK(state);
1061
1062         return (action);
1063 }
1064
1065 /* Check if char is waiting */
1066 static int
1067 vkbd_check_char(keyboard_t *kbd)
1068 {
1069         vkbd_state_t    *state = NULL;
1070         int              ready;
1071
1072         if (!KBD_IS_ACTIVE(kbd))
1073                 return (FALSE);
1074
1075         state = (vkbd_state_t *) kbd->kb_data;
1076         
1077         VKBD_LOCK(state);
1078         if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0))
1079                 ready = TRUE;
1080         else
1081                 ready = vkbd_data_ready(state);
1082         VKBD_UNLOCK(state);
1083
1084         return (ready);
1085 }
1086
1087 /* Some useful control functions (stolen from atkbd.c) */
1088 static int
1089 vkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
1090 {
1091         vkbd_state_t    *state = (vkbd_state_t *) kbd->kb_data;
1092         int              i;
1093 #ifdef COMPAT_FREEBSD6
1094         int              ival;
1095 #endif
1096
1097         VKBD_LOCK(state);
1098
1099         switch (cmd) {
1100         case KDGKBMODE:         /* get keyboard mode */
1101                 *(int *)arg = state->ks_mode;
1102                 break;
1103
1104 #ifdef COMPAT_FREEBSD6
1105         case _IO('K', 7):
1106                 ival = IOCPARM_IVAL(arg);
1107                 arg = (caddr_t)&ival;
1108                 /* FALLTHROUGH */
1109 #endif
1110         case KDSKBMODE:         /* set keyboard mode */
1111                 switch (*(int *)arg) {
1112                 case K_XLATE:
1113                         if (state->ks_mode != K_XLATE) {
1114                                 /* make lock key state and LED state match */
1115                                 state->ks_state &= ~LOCK_MASK;
1116                                 state->ks_state |= KBD_LED_VAL(kbd);
1117                                 vkbd_status_changed(state);
1118                         }
1119                         /* FALLTHROUGH */
1120
1121                 case K_RAW:
1122                 case K_CODE:
1123                         if (state->ks_mode != *(int *)arg) {
1124                                 vkbd_clear_state_locked(state);
1125                                 state->ks_mode = *(int *)arg;
1126                                 vkbd_status_changed(state);
1127                         }
1128                         break;
1129
1130                 default:
1131                         VKBD_UNLOCK(state);
1132                         return (EINVAL);
1133                 }
1134                 break;
1135
1136         case KDGETLED:          /* get keyboard LED */
1137                 *(int *)arg = KBD_LED_VAL(kbd);
1138                 break;
1139
1140 #ifdef COMPAT_FREEBSD6
1141         case _IO('K', 66):
1142                 ival = IOCPARM_IVAL(arg);
1143                 arg = (caddr_t)&ival;
1144                 /* FALLTHROUGH */
1145 #endif
1146         case KDSETLED:          /* set keyboard LED */
1147                 /* NOTE: lock key state in ks_state won't be changed */
1148                 if (*(int *)arg & ~LOCK_MASK) {
1149                         VKBD_UNLOCK(state);
1150                         return (EINVAL);
1151                 }
1152
1153                 i = *(int *)arg;
1154                 /* replace CAPS LED with ALTGR LED for ALTGR keyboards */
1155                 if (state->ks_mode == K_XLATE &&
1156                     kbd->kb_keymap->n_keys > ALTGR_OFFSET) {
1157                         if (i & ALKED)
1158                                 i |= CLKED;
1159                         else
1160                                 i &= ~CLKED;
1161                 }
1162
1163                 KBD_LED_VAL(kbd) = *(int *)arg;
1164                 vkbd_status_changed(state);
1165                 break;
1166
1167         case KDGKBSTATE:        /* get lock key state */
1168                 *(int *)arg = state->ks_state & LOCK_MASK;
1169                 break;
1170
1171 #ifdef COMPAT_FREEBSD6
1172         case _IO('K', 20):
1173                 ival = IOCPARM_IVAL(arg);
1174                 arg = (caddr_t)&ival;
1175                 /* FALLTHROUGH */
1176 #endif
1177         case KDSKBSTATE:        /* set lock key state */
1178                 if (*(int *)arg & ~LOCK_MASK) {
1179                         VKBD_UNLOCK(state);
1180                         return (EINVAL);
1181                 }
1182                 state->ks_state &= ~LOCK_MASK;
1183                 state->ks_state |= *(int *)arg;
1184                 vkbd_status_changed(state);
1185                 VKBD_UNLOCK(state);
1186                 /* set LEDs and quit */
1187                 return (vkbd_ioctl(kbd, KDSETLED, arg));
1188
1189         case KDSETREPEAT:       /* set keyboard repeat rate (new interface) */
1190                 i = typematic(((int *)arg)[0], ((int *)arg)[1]);
1191                 kbd->kb_delay1 = typematic_delay(i);
1192                 kbd->kb_delay2 = typematic_rate(i);
1193                 vkbd_status_changed(state);
1194                 break;
1195
1196 #ifdef COMPAT_FREEBSD6
1197         case _IO('K', 67):
1198                 ival = IOCPARM_IVAL(arg);
1199                 arg = (caddr_t)&ival;
1200                 /* FALLTHROUGH */
1201 #endif
1202         case KDSETRAD:          /* set keyboard repeat rate (old interface) */
1203                 kbd->kb_delay1 = typematic_delay(*(int *)arg);
1204                 kbd->kb_delay2 = typematic_rate(*(int *)arg);
1205                 vkbd_status_changed(state);
1206                 break;
1207
1208         case PIO_KEYMAP:        /* set keyboard translation table */
1209         case OPIO_KEYMAP:       /* set keyboard translation table (compat) */
1210         case PIO_KEYMAPENT:     /* set keyboard translation table entry */
1211         case PIO_DEADKEYMAP:    /* set accent key translation table */
1212                 state->ks_accents = 0;
1213                 /* FALLTHROUGH */
1214
1215         default:
1216                 VKBD_UNLOCK(state);
1217                 return (genkbd_commonioctl(kbd, cmd, arg));
1218         }
1219
1220         VKBD_UNLOCK(state);
1221
1222         return (0);
1223 }
1224
1225 /* Lock the access to the keyboard */
1226 static int
1227 vkbd_lock(keyboard_t *kbd, int lock)
1228 {
1229         return (1); /* XXX */
1230 }
1231
1232 /* Clear the internal state of the keyboard */
1233 static void
1234 vkbd_clear_state_locked(vkbd_state_t *state)
1235 {
1236         VKBD_LOCK_ASSERT(state, MA_OWNED);
1237
1238         state->ks_flags &= ~COMPOSE;
1239         state->ks_polling = 0;
1240         state->ks_state &= LOCK_MASK;   /* preserve locking key state */
1241         state->ks_accents = 0;
1242         state->ks_composed_char = 0;
1243 /*      state->ks_prefix = 0;           XXX */
1244
1245         /* flush ks_inq and wakeup writers/poll()ers */
1246         state->ks_inq.head = state->ks_inq.tail = state->ks_inq.cc = 0;
1247         selwakeuppri(&state->ks_wsel, PZERO + 1);
1248         wakeup(&state->ks_inq);
1249 }
1250
1251 static void
1252 vkbd_clear_state(keyboard_t *kbd)
1253 {
1254         vkbd_state_t    *state = (vkbd_state_t *) kbd->kb_data;
1255
1256         VKBD_LOCK(state);
1257         vkbd_clear_state_locked(state);
1258         VKBD_UNLOCK(state);
1259 }
1260
1261 /* Save the internal state */
1262 static int
1263 vkbd_get_state(keyboard_t *kbd, void *buf, size_t len)
1264 {
1265         if (len == 0)
1266                 return (sizeof(vkbd_state_t));
1267         if (len < sizeof(vkbd_state_t))
1268                 return (-1);
1269         bcopy(kbd->kb_data, buf, sizeof(vkbd_state_t)); /* XXX locking? */
1270         return (0);
1271 }
1272
1273 /* Set the internal state */
1274 static int
1275 vkbd_set_state(keyboard_t *kbd, void *buf, size_t len)
1276 {
1277         if (len < sizeof(vkbd_state_t))
1278                 return (ENOMEM);
1279         bcopy(buf, kbd->kb_data, sizeof(vkbd_state_t)); /* XXX locking? */
1280         return (0);
1281 }
1282
1283 /* Set polling */
1284 static int
1285 vkbd_poll(keyboard_t *kbd, int on)
1286 {
1287         vkbd_state_t    *state = NULL;
1288
1289         state = (vkbd_state_t *) kbd->kb_data;
1290
1291         VKBD_LOCK(state);
1292
1293         if (on)
1294                 state->ks_polling ++;
1295         else
1296                 state->ks_polling --;
1297
1298         VKBD_UNLOCK(state);
1299
1300         return (0);
1301 }
1302
1303 /*
1304  * Local functions
1305  */
1306
1307 static int delays[] = { 250, 500, 750, 1000 };
1308 static int rates[] = {  34,  38,  42,  46,  50,  55,  59,  63,
1309                         68,  76,  84,  92, 100, 110, 118, 126,
1310                         136, 152, 168, 184, 200, 220, 236, 252,
1311                         272, 304, 336, 368, 400, 440, 472, 504 };
1312
1313 static int
1314 typematic_delay(int i)
1315 {
1316         return (delays[(i >> 5) & 3]);
1317 }
1318
1319 static int
1320 typematic_rate(int i)
1321 {
1322         return (rates[i & 0x1f]);
1323 }
1324
1325 static int
1326 typematic(int delay, int rate)
1327 {
1328         int value;
1329         int i;
1330
1331         for (i = nitems(delays) - 1; i > 0; i --) {
1332                 if (delay >= delays[i])
1333                         break;
1334         }
1335         value = i << 5;
1336         for (i = nitems(rates) - 1; i > 0; i --) {
1337                 if (rate >= rates[i])
1338                         break;
1339         }
1340         value |= i;
1341         return (value);
1342 }
1343
1344 /*****************************************************************************
1345  *****************************************************************************
1346  **                                    Module 
1347  *****************************************************************************
1348  *****************************************************************************/
1349
1350 KEYBOARD_DRIVER(vkbd, vkbdsw, vkbd_configure);
1351
1352 static int
1353 vkbd_modevent(module_t mod, int type, void *data)
1354 {
1355         static eventhandler_tag tag;
1356
1357         switch (type) {
1358         case MOD_LOAD:
1359                 clone_setup(&vkbd_dev_clones);
1360                 tag = EVENTHANDLER_REGISTER(dev_clone, vkbd_dev_clone, 0, 1000);
1361                 if (tag == NULL) {
1362                         clone_cleanup(&vkbd_dev_clones);
1363                         return (ENOMEM);
1364                 }
1365                 kbd_add_driver(&vkbd_kbd_driver);
1366                 break;
1367
1368         case MOD_UNLOAD:
1369                 kbd_delete_driver(&vkbd_kbd_driver);
1370                 EVENTHANDLER_DEREGISTER(dev_clone, tag);
1371                 clone_cleanup(&vkbd_dev_clones);
1372                 break;
1373
1374         default:
1375                 return (EOPNOTSUPP);
1376         }
1377
1378         return (0);
1379 }
1380
1381 DEV_MODULE(vkbd, vkbd_modevent, NULL);
1382