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