]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/dev/vkbd/vkbd.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.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,
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, unit2minor(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         (*kbdsw[kbd->kb_index]->disable)(kbd);
282 #ifdef KBD_INSTALL_CDEV
283         kbd_detach(kbd);
284 #endif /* def KBD_INSTALL_CDEV */
285         (*kbdsw[kbd->kb_index]->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 : 
441                         (*kbdsw[kbd->kb_index]->ioctl)(kbd, cmd, data));
442 }
443
444 /* Poll device */
445 static int
446 vkbd_dev_poll(struct cdev *dev, int events, struct thread *td)
447 {
448         vkbd_state_t    *state = (vkbd_state_t *) dev->si_drv1;
449         vkbd_queue_t    *q = NULL;
450         int              revents = 0;
451
452         if (state == NULL)
453                 return (ENXIO);
454
455         VKBD_LOCK(state);
456
457         q = &state->ks_inq;
458
459         if (events & (POLLIN | POLLRDNORM)) {
460                 if (state->ks_flags & STATUS)
461                         revents |= events & (POLLIN | POLLRDNORM);
462                 else
463                         selrecord(td, &state->ks_rsel);
464         }
465
466         if (events & (POLLOUT | POLLWRNORM)) {
467                 if (q->cc < sizeof(q->q)/sizeof(q->q[0]))
468                         revents |= events & (POLLOUT | POLLWRNORM);
469                 else
470                         selrecord(td, &state->ks_wsel);
471         }
472
473         VKBD_UNLOCK(state);
474
475         return (revents);
476 }
477
478 /* Interrupt handler */
479 void
480 vkbd_dev_intr(void *xkbd, int pending)
481 {
482         keyboard_t      *kbd = (keyboard_t *) xkbd;
483         vkbd_state_t    *state = (vkbd_state_t *) kbd->kb_data;
484
485         (*kbdsw[kbd->kb_index]->intr)(kbd, NULL);
486
487         VKBD_LOCK(state);
488
489         state->ks_flags &= ~TASK;
490         wakeup(&state->ks_task);
491
492         VKBD_UNLOCK(state);
493 }
494
495 /* Set status change flags */
496 static void
497 vkbd_status_changed(vkbd_state_t *state)
498 {
499         VKBD_LOCK_ASSERT(state, MA_OWNED);
500
501         if (!(state->ks_flags & STATUS)) {
502                 state->ks_flags |= STATUS;
503                 selwakeuppri(&state->ks_rsel, PZERO + 1);
504                 wakeup(&state->ks_flags);
505         }
506 }
507
508 /* Check if we have data in the input queue */
509 static int
510 vkbd_data_ready(vkbd_state_t *state)
511 {
512         VKBD_LOCK_ASSERT(state, MA_OWNED);
513
514         return (state->ks_inq.cc > 0);
515 }
516
517 /* Read one code from the input queue */
518 static int
519 vkbd_data_read(vkbd_state_t *state, int wait)
520 {
521         vkbd_queue_t    *q = &state->ks_inq;
522         int              c;
523
524         VKBD_LOCK_ASSERT(state, MA_OWNED);
525
526         if (q->cc == 0)
527                 return (-1);
528
529         /* get first code from the queue */
530         q->cc --;
531         c = q->q[q->head ++];
532         if (q->head == sizeof(q->q)/sizeof(q->q[0]))
533                 q->head = 0;
534
535         /* wakeup ks_inq writers/poll()ers */
536         selwakeuppri(&state->ks_wsel, PZERO + 1);
537         wakeup(q);
538
539         return (c);
540 }
541
542 /****************************************************************************
543  ****************************************************************************
544  **                              Keyboard driver
545  ****************************************************************************
546  ****************************************************************************/
547
548 static int              vkbd_configure(int flags);
549 static kbd_probe_t      vkbd_probe;
550 static kbd_init_t       vkbd_init;
551 static kbd_term_t       vkbd_term;
552 static kbd_intr_t       vkbd_intr;
553 static kbd_test_if_t    vkbd_test_if;
554 static kbd_enable_t     vkbd_enable;
555 static kbd_disable_t    vkbd_disable;
556 static kbd_read_t       vkbd_read;
557 static kbd_check_t      vkbd_check;
558 static kbd_read_char_t  vkbd_read_char;
559 static kbd_check_char_t vkbd_check_char;
560 static kbd_ioctl_t      vkbd_ioctl;
561 static kbd_lock_t       vkbd_lock;
562 static void             vkbd_clear_state_locked(vkbd_state_t *state);
563 static kbd_clear_state_t vkbd_clear_state;
564 static kbd_get_state_t  vkbd_get_state;
565 static kbd_set_state_t  vkbd_set_state;
566 static kbd_poll_mode_t  vkbd_poll;
567
568 static keyboard_switch_t vkbdsw = {
569         .probe =        vkbd_probe,
570         .init =         vkbd_init,
571         .term =         vkbd_term,
572         .intr =         vkbd_intr,
573         .test_if =      vkbd_test_if,
574         .enable =       vkbd_enable,
575         .disable =      vkbd_disable,
576         .read =         vkbd_read,
577         .check =        vkbd_check,
578         .read_char =    vkbd_read_char,
579         .check_char =   vkbd_check_char,
580         .ioctl =        vkbd_ioctl,
581         .lock =         vkbd_lock,
582         .clear_state =  vkbd_clear_state,
583         .get_state =    vkbd_get_state,
584         .set_state =    vkbd_set_state,
585         .get_fkeystr =  genkbd_get_fkeystr,
586         .poll =         vkbd_poll,
587         .diag =         genkbd_diag,
588 };
589
590 static int      typematic(int delay, int rate);
591 static int      typematic_delay(int delay);
592 static int      typematic_rate(int rate);
593
594 /* Return the number of found keyboards */
595 static int
596 vkbd_configure(int flags)
597 {
598         return (1);
599 }
600
601 /* Detect a keyboard */
602 static int
603 vkbd_probe(int unit, void *arg, int flags)
604 {
605         return (0);
606 }
607
608 /* Reset and initialize the keyboard (stolen from atkbd.c) */
609 static int
610 vkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
611 {
612         keyboard_t      *kbd = NULL;
613         vkbd_state_t    *state = NULL;
614         keymap_t        *keymap = NULL;
615         accentmap_t     *accmap = NULL;
616         fkeytab_t       *fkeymap = NULL;
617         int              fkeymap_size, delay[2];
618         int              error, needfree;
619
620         if (*kbdp == NULL) {
621                 *kbdp = kbd = malloc(sizeof(*kbd), M_VKBD, M_NOWAIT | M_ZERO);
622                 state = malloc(sizeof(*state), M_VKBD, M_NOWAIT | M_ZERO);
623                 keymap = malloc(sizeof(key_map), M_VKBD, M_NOWAIT);
624                 accmap = malloc(sizeof(accent_map), M_VKBD, M_NOWAIT);
625                 fkeymap = malloc(sizeof(fkey_tab), M_VKBD, M_NOWAIT);
626                 fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
627                 needfree = 1;
628                 if ((kbd == NULL) || (state == NULL) || (keymap == NULL) ||
629                     (accmap == NULL) || (fkeymap == NULL)) {
630                         error = ENOMEM;
631                         goto bad;
632                 }
633
634                 VKBD_LOCK_INIT(state);
635                 state->ks_inq.head = state->ks_inq.tail = state->ks_inq.cc = 0;
636                 TASK_INIT(&state->ks_task, 0, vkbd_dev_intr, (void *) kbd);
637         } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
638                 return (0);
639         } else {
640                 kbd = *kbdp;
641                 state = (vkbd_state_t *) kbd->kb_data;
642                 keymap = kbd->kb_keymap;
643                 accmap = kbd->kb_accentmap;
644                 fkeymap = kbd->kb_fkeytab;
645                 fkeymap_size = kbd->kb_fkeytab_size;
646                 needfree = 0;
647         }
648
649         if (!KBD_IS_PROBED(kbd)) {
650                 kbd_init_struct(kbd, KEYBOARD_NAME, KB_OTHER, unit, flags, 0, 0);
651                 bcopy(&key_map, keymap, sizeof(key_map));
652                 bcopy(&accent_map, accmap, sizeof(accent_map));
653                 bcopy(fkey_tab, fkeymap,
654                         imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
655                 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
656                 kbd->kb_data = (void *)state;
657         
658                 KBD_FOUND_DEVICE(kbd);
659                 KBD_PROBE_DONE(kbd);
660
661                 VKBD_LOCK(state);
662                 vkbd_clear_state_locked(state);
663                 state->ks_mode = K_XLATE;
664                 /* FIXME: set the initial value for lock keys in ks_state */
665                 VKBD_UNLOCK(state);
666         }
667         if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
668                 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
669
670                 vkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
671                 delay[0] = kbd->kb_delay1;
672                 delay[1] = kbd->kb_delay2;
673                 vkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
674
675                 KBD_INIT_DONE(kbd);
676         }
677         if (!KBD_IS_CONFIGURED(kbd)) {
678                 if (kbd_register(kbd) < 0) {
679                         error = ENXIO;
680                         goto bad;
681                 }
682                 KBD_CONFIG_DONE(kbd);
683         }
684
685         return (0);
686 bad:
687         if (needfree) {
688                 if (state != NULL)
689                         free(state, M_VKBD);
690                 if (keymap != NULL)
691                         free(keymap, M_VKBD);
692                 if (accmap != NULL)
693                         free(accmap, M_VKBD);
694                 if (fkeymap != NULL)
695                         free(fkeymap, M_VKBD);
696                 if (kbd != NULL) {
697                         free(kbd, M_VKBD);
698                         *kbdp = NULL;   /* insure ref doesn't leak to caller */
699                 }
700         }
701         return (error);
702 }
703
704 /* Finish using this keyboard */
705 static int
706 vkbd_term(keyboard_t *kbd)
707 {
708         vkbd_state_t    *state = (vkbd_state_t *) kbd->kb_data;
709
710         kbd_unregister(kbd);
711
712         VKBD_LOCK_DESTROY(state);
713         bzero(state, sizeof(*state));
714         free(state, M_VKBD);
715
716         free(kbd->kb_keymap, M_VKBD);
717         free(kbd->kb_accentmap, M_VKBD);
718         free(kbd->kb_fkeytab, M_VKBD);
719         free(kbd, M_VKBD);
720
721         return (0);
722 }
723
724 /* Keyboard interrupt routine */
725 static int
726 vkbd_intr(keyboard_t *kbd, void *arg)
727 {
728         int     c;
729
730         if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
731                 /* let the callback function to process the input */
732                 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
733                                             kbd->kb_callback.kc_arg);
734         } else {
735                 /* read and discard the input; no one is waiting for input */
736                 do {
737                         c = vkbd_read_char(kbd, FALSE);
738                 } while (c != NOKEY);
739         }
740
741         return (0);
742 }
743
744 /* Test the interface to the device */
745 static int
746 vkbd_test_if(keyboard_t *kbd)
747 {
748         return (0);
749 }
750
751 /* 
752  * Enable the access to the device; until this function is called,
753  * the client cannot read from the keyboard.
754  */
755
756 static int
757 vkbd_enable(keyboard_t *kbd)
758 {
759         KBD_ACTIVATE(kbd);
760         return (0);
761 }
762
763 /* Disallow the access to the device */
764 static int
765 vkbd_disable(keyboard_t *kbd)
766 {
767         KBD_DEACTIVATE(kbd);
768         return (0);
769 }
770
771 /* Read one byte from the keyboard if it's allowed */
772 static int
773 vkbd_read(keyboard_t *kbd, int wait)
774 {
775         vkbd_state_t    *state = (vkbd_state_t *) kbd->kb_data;
776         int              c;
777
778         VKBD_LOCK(state);
779         c = vkbd_data_read(state, wait);
780         VKBD_UNLOCK(state);
781
782         if (c != -1)
783                 kbd->kb_count ++;
784
785         return (KBD_IS_ACTIVE(kbd)? c : -1);
786 }
787
788 /* Check if data is waiting */
789 static int
790 vkbd_check(keyboard_t *kbd)
791 {
792         vkbd_state_t    *state = NULL;
793         int              ready;
794
795         if (!KBD_IS_ACTIVE(kbd))
796                 return (FALSE);
797
798         state = (vkbd_state_t *) kbd->kb_data;
799
800         VKBD_LOCK(state);
801         ready = vkbd_data_ready(state);
802         VKBD_UNLOCK(state);
803
804         return (ready);
805 }
806
807 /* Read char from the keyboard (stolen from atkbd.c) */
808 static u_int
809 vkbd_read_char(keyboard_t *kbd, int wait)
810 {
811         vkbd_state_t    *state = (vkbd_state_t *) kbd->kb_data;
812         u_int            action;
813         int              scancode, keycode;
814
815         VKBD_LOCK(state);
816
817 next_code:
818
819         /* do we have a composed char to return? */
820         if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
821                 action = state->ks_composed_char;
822                 state->ks_composed_char = 0;
823                 if (action > UCHAR_MAX) {
824                         VKBD_UNLOCK(state);
825                         return (ERRKEY);
826                 }
827
828                 VKBD_UNLOCK(state);
829                 return (action);
830         }
831
832         /* see if there is something in the keyboard port */
833         scancode = vkbd_data_read(state, wait);
834         if (scancode == -1) {
835                 VKBD_UNLOCK(state);
836                 return (NOKEY);
837         }
838         /* XXX FIXME: check for -1 if wait == 1! */
839
840         kbd->kb_count ++;
841
842         /* return the byte as is for the K_RAW mode */
843         if (state->ks_mode == K_RAW) {
844                 VKBD_UNLOCK(state);
845                 return (scancode);
846         }
847
848         /* translate the scan code into a keycode */
849         keycode = scancode & 0x7F;
850         switch (state->ks_prefix) {
851         case 0x00:      /* normal scancode */
852                 switch(scancode) {
853                 case 0xB8:      /* left alt (compose key) released */
854                         if (state->ks_flags & COMPOSE) {
855                                 state->ks_flags &= ~COMPOSE;
856                                 if (state->ks_composed_char > UCHAR_MAX)
857                                         state->ks_composed_char = 0;
858                         }
859                         break;
860                 case 0x38:      /* left alt (compose key) pressed */
861                         if (!(state->ks_flags & COMPOSE)) {
862                                 state->ks_flags |= COMPOSE;
863                                 state->ks_composed_char = 0;
864                         }
865                         break;
866                 case 0xE0:
867                 case 0xE1:
868                         state->ks_prefix = scancode;
869                         goto next_code;
870                 }
871                 break;
872         case 0xE0:      /* 0xE0 prefix */
873                 state->ks_prefix = 0;
874                 switch (keycode) {
875                 case 0x1C:      /* right enter key */
876                         keycode = 0x59;
877                         break;
878                 case 0x1D:      /* right ctrl key */
879                         keycode = 0x5A;
880                         break;
881                 case 0x35:      /* keypad divide key */
882                         keycode = 0x5B;
883                         break;
884                 case 0x37:      /* print scrn key */
885                         keycode = 0x5C;
886                         break;
887                 case 0x38:      /* right alt key (alt gr) */
888                         keycode = 0x5D;
889                         break;
890                 case 0x46:      /* ctrl-pause/break on AT 101 (see below) */
891                         keycode = 0x68;
892                         break;
893                 case 0x47:      /* grey home key */
894                         keycode = 0x5E;
895                         break;
896                 case 0x48:      /* grey up arrow key */
897                         keycode = 0x5F;
898                         break;
899                 case 0x49:      /* grey page up key */
900                         keycode = 0x60;
901                         break;
902                 case 0x4B:      /* grey left arrow key */
903                         keycode = 0x61;
904                         break;
905                 case 0x4D:      /* grey right arrow key */
906                         keycode = 0x62;
907                         break;
908                 case 0x4F:      /* grey end key */
909                         keycode = 0x63;
910                         break;
911                 case 0x50:      /* grey down arrow key */
912                         keycode = 0x64;
913                         break;
914                 case 0x51:      /* grey page down key */
915                         keycode = 0x65;
916                         break;
917                 case 0x52:      /* grey insert key */
918                         keycode = 0x66;
919                         break;
920                 case 0x53:      /* grey delete key */
921                         keycode = 0x67;
922                         break;
923                 /* the following 3 are only used on the MS "Natural" keyboard */
924                 case 0x5b:      /* left Window key */
925                         keycode = 0x69;
926                         break;
927                 case 0x5c:      /* right Window key */
928                         keycode = 0x6a;
929                         break;
930                 case 0x5d:      /* menu key */
931                         keycode = 0x6b;
932                         break;
933                 case 0x5e:      /* power key */
934                         keycode = 0x6d;
935                         break;
936                 case 0x5f:      /* sleep key */
937                         keycode = 0x6e;
938                         break;
939                 case 0x63:      /* wake key */
940                         keycode = 0x6f;
941                         break;
942                 default:        /* ignore everything else */
943                         goto next_code;
944                 }
945                 break;
946         case 0xE1:      /* 0xE1 prefix */
947                 /* 
948                  * The pause/break key on the 101 keyboard produces:
949                  * E1-1D-45 E1-9D-C5
950                  * Ctrl-pause/break produces:
951                  * E0-46 E0-C6 (See above.)
952                  */
953                 state->ks_prefix = 0;
954                 if (keycode == 0x1D)
955                         state->ks_prefix = 0x1D;
956                 goto next_code;
957                 /* NOT REACHED */
958         case 0x1D:      /* pause / break */
959                 state->ks_prefix = 0;
960                 if (keycode != 0x45)
961                         goto next_code;
962                 keycode = 0x68;
963                 break;
964         }
965
966         if (kbd->kb_type == KB_84) {
967                 switch (keycode) {
968                 case 0x37:      /* *(numpad)/print screen */
969                         if (state->ks_flags & SHIFTS)
970                                 keycode = 0x5c; /* print screen */
971                         break;
972                 case 0x45:      /* num lock/pause */
973                         if (state->ks_flags & CTLS)
974                                 keycode = 0x68; /* pause */
975                         break;
976                 case 0x46:      /* scroll lock/break */
977                         if (state->ks_flags & CTLS)
978                                 keycode = 0x6c; /* break */
979                         break;
980                 }
981         } else if (kbd->kb_type == KB_101) {
982                 switch (keycode) {
983                 case 0x5c:      /* print screen */
984                         if (state->ks_flags & ALTS)
985                                 keycode = 0x54; /* sysrq */
986                         break;
987                 case 0x68:      /* pause/break */
988                         if (state->ks_flags & CTLS)
989                                 keycode = 0x6c; /* break */
990                         break;
991                 }
992         }
993
994         /* return the key code in the K_CODE mode */
995         if (state->ks_mode == K_CODE) {
996                 VKBD_UNLOCK(state);
997                 return (keycode | (scancode & 0x80));
998         }
999
1000         /* compose a character code */
1001         if (state->ks_flags & COMPOSE) {
1002                 switch (keycode | (scancode & 0x80)) {
1003                 /* key pressed, process it */
1004                 case 0x47: case 0x48: case 0x49:        /* keypad 7,8,9 */
1005                         state->ks_composed_char *= 10;
1006                         state->ks_composed_char += keycode - 0x40;
1007                         if (state->ks_composed_char > UCHAR_MAX) {
1008                                 VKBD_UNLOCK(state);
1009                                 return (ERRKEY);
1010                         }
1011                         goto next_code;
1012                 case 0x4B: case 0x4C: case 0x4D:        /* keypad 4,5,6 */
1013                         state->ks_composed_char *= 10;
1014                         state->ks_composed_char += keycode - 0x47;
1015                         if (state->ks_composed_char > UCHAR_MAX) {
1016                                 VKBD_UNLOCK(state);
1017                                 return (ERRKEY);
1018                         }
1019                         goto next_code;
1020                 case 0x4F: case 0x50: case 0x51:        /* keypad 1,2,3 */
1021                         state->ks_composed_char *= 10;
1022                         state->ks_composed_char += keycode - 0x4E;
1023                         if (state->ks_composed_char > UCHAR_MAX) {
1024                                 VKBD_UNLOCK(state);
1025                                 return (ERRKEY);
1026                         }
1027                         goto next_code;
1028                 case 0x52:      /* keypad 0 */
1029                         state->ks_composed_char *= 10;
1030                         if (state->ks_composed_char > UCHAR_MAX) {
1031                                 VKBD_UNLOCK(state);
1032                                 return (ERRKEY);
1033                         }
1034                         goto next_code;
1035
1036                 /* key released, no interest here */
1037                 case 0xC7: case 0xC8: case 0xC9:        /* keypad 7,8,9 */
1038                 case 0xCB: case 0xCC: case 0xCD:        /* keypad 4,5,6 */
1039                 case 0xCF: case 0xD0: case 0xD1:        /* keypad 1,2,3 */
1040                 case 0xD2:                              /* keypad 0 */
1041                         goto next_code;
1042
1043                 case 0x38:                              /* left alt key */
1044                         break;
1045
1046                 default:
1047                         if (state->ks_composed_char > 0) {
1048                                 state->ks_flags &= ~COMPOSE;
1049                                 state->ks_composed_char = 0;
1050                                 VKBD_UNLOCK(state);
1051                                 return (ERRKEY);
1052                         }
1053                         break;
1054                 }
1055         }
1056
1057         /* keycode to key action */
1058         action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
1059                         &state->ks_state, &state->ks_accents);
1060         if (action == NOKEY)
1061                 goto next_code;
1062
1063         VKBD_UNLOCK(state);
1064
1065         return (action);
1066 }
1067
1068 /* Check if char is waiting */
1069 static int
1070 vkbd_check_char(keyboard_t *kbd)
1071 {
1072         vkbd_state_t    *state = NULL;
1073         int              ready;
1074
1075         if (!KBD_IS_ACTIVE(kbd))
1076                 return (FALSE);
1077
1078         state = (vkbd_state_t *) kbd->kb_data;
1079         
1080         VKBD_LOCK(state);
1081         if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0))
1082                 ready = TRUE;
1083         else
1084                 ready = vkbd_data_ready(state);
1085         VKBD_UNLOCK(state);
1086
1087         return (ready);
1088 }
1089
1090 /* Some useful control functions (stolen from atkbd.c) */
1091 static int
1092 vkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
1093 {
1094         vkbd_state_t    *state = (vkbd_state_t *) kbd->kb_data;
1095         int              i;
1096 #ifdef COMPAT_FREEBSD6
1097         int              ival;
1098 #endif
1099
1100         VKBD_LOCK(state);
1101
1102         switch (cmd) {
1103         case KDGKBMODE:         /* get keyboard mode */
1104                 *(int *)arg = state->ks_mode;
1105                 break;
1106
1107 #ifdef COMPAT_FREEBSD6
1108         case _IO('K', 7):
1109                 ival = IOCPARM_IVAL(arg);
1110                 arg = (caddr_t)&ival;
1111                 /* FALLTHROUGH */
1112 #endif
1113         case KDSKBMODE:         /* set keyboard mode */
1114                 switch (*(int *)arg) {
1115                 case K_XLATE:
1116                         if (state->ks_mode != K_XLATE) {
1117                                 /* make lock key state and LED state match */
1118                                 state->ks_state &= ~LOCK_MASK;
1119                                 state->ks_state |= KBD_LED_VAL(kbd);
1120                                 vkbd_status_changed(state);
1121                         }
1122                         /* FALLTHROUGH */
1123
1124                 case K_RAW:
1125                 case K_CODE:
1126                         if (state->ks_mode != *(int *)arg) {
1127                                 vkbd_clear_state_locked(state);
1128                                 state->ks_mode = *(int *)arg;
1129                                 vkbd_status_changed(state);
1130                         }
1131                         break;
1132
1133                 default:
1134                         VKBD_UNLOCK(state);
1135                         return (EINVAL);
1136                 }
1137                 break;
1138
1139         case KDGETLED:          /* get keyboard LED */
1140                 *(int *)arg = KBD_LED_VAL(kbd);
1141                 break;
1142
1143 #ifdef COMPAT_FREEBSD6
1144         case _IO('K', 66):
1145                 ival = IOCPARM_IVAL(arg);
1146                 arg = (caddr_t)&ival;
1147                 /* FALLTHROUGH */
1148 #endif
1149         case KDSETLED:          /* set keyboard LED */
1150                 /* NOTE: lock key state in ks_state won't be changed */
1151                 if (*(int *)arg & ~LOCK_MASK) {
1152                         VKBD_UNLOCK(state);
1153                         return (EINVAL);
1154                 }
1155
1156                 i = *(int *)arg;
1157                 /* replace CAPS LED with ALTGR LED for ALTGR keyboards */
1158                 if (state->ks_mode == K_XLATE &&
1159                     kbd->kb_keymap->n_keys > ALTGR_OFFSET) {
1160                         if (i & ALKED)
1161                                 i |= CLKED;
1162                         else
1163                                 i &= ~CLKED;
1164                 }
1165
1166                 KBD_LED_VAL(kbd) = *(int *)arg;
1167                 vkbd_status_changed(state);
1168                 break;
1169
1170         case KDGKBSTATE:        /* get lock key state */
1171                 *(int *)arg = state->ks_state & LOCK_MASK;
1172                 break;
1173
1174 #ifdef COMPAT_FREEBSD6
1175         case _IO('K', 20):
1176                 ival = IOCPARM_IVAL(arg);
1177                 arg = (caddr_t)&ival;
1178                 /* FALLTHROUGH */
1179 #endif
1180         case KDSKBSTATE:        /* set lock key state */
1181                 if (*(int *)arg & ~LOCK_MASK) {
1182                         VKBD_UNLOCK(state);
1183                         return (EINVAL);
1184                 }
1185                 state->ks_state &= ~LOCK_MASK;
1186                 state->ks_state |= *(int *)arg;
1187                 vkbd_status_changed(state);
1188                 VKBD_UNLOCK(state);
1189                 /* set LEDs and quit */
1190                 return (vkbd_ioctl(kbd, KDSETLED, arg));
1191
1192         case KDSETREPEAT:       /* set keyboard repeat rate (new interface) */
1193                 i = typematic(((int *)arg)[0], ((int *)arg)[1]);
1194                 kbd->kb_delay1 = typematic_delay(i);
1195                 kbd->kb_delay2 = typematic_rate(i);
1196                 vkbd_status_changed(state);
1197                 break;
1198
1199 #ifdef COMPAT_FREEBSD6
1200         case _IO('K', 67):
1201                 ival = IOCPARM_IVAL(arg);
1202                 arg = (caddr_t)&ival;
1203                 /* FALLTHROUGH */
1204 #endif
1205         case KDSETRAD:          /* set keyboard repeat rate (old interface) */
1206                 kbd->kb_delay1 = typematic_delay(*(int *)arg);
1207                 kbd->kb_delay2 = typematic_rate(*(int *)arg);
1208                 vkbd_status_changed(state);
1209                 break;
1210
1211         case PIO_KEYMAP:        /* set keyboard translation table */
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