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
61MALLOC_DECLARE(M_VKBD);
62MALLOC_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 */
99struct 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
107typedef struct vkbd_queue	vkbd_queue_t;
108
109/* vkbd state */
110struct 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
138typedef struct vkbd_state	vkbd_state_t;
139
140/*****************************************************************************
141 *****************************************************************************
142 **                             Character device
143 *****************************************************************************
144 *****************************************************************************/
145
146static void		vkbd_dev_clone(void *, struct ucred *, char *, int,
147			    struct cdev **);
148static d_open_t		vkbd_dev_open;
149static d_close_t	vkbd_dev_close;
150static d_read_t		vkbd_dev_read;
151static d_write_t	vkbd_dev_write;
152static d_ioctl_t	vkbd_dev_ioctl;
153static d_poll_t		vkbd_dev_poll;
154static void		vkbd_dev_intr(void *, int);
155static void		vkbd_status_changed(vkbd_state_t *);
156static int		vkbd_data_ready(vkbd_state_t *);
157static int		vkbd_data_read(vkbd_state_t *, int);
158
159static 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
171static struct clonedevs	*vkbd_dev_clones = NULL;
172
173/* Clone device */
174static void
175vkbd_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 */
200static int
201vkbd_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 */
251static int
252vkbd_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 */
294static int
295vkbd_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;
321again:
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	}
345done:
346	state->ks_flags &= ~READ;
347
348	VKBD_UNLOCK(state);
349
350	return (error);
351}
352
353/* Write scancodes */
354static int
355vkbd_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 */
435static int
436vkbd_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 */
444static int
445vkbd_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 */
478void
479vkbd_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 */
495static void
496vkbd_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 */
508static int
509vkbd_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 */
517static int
518vkbd_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
547static int		vkbd_configure(int flags);
548static kbd_probe_t	vkbd_probe;
549static kbd_init_t	vkbd_init;
550static kbd_term_t	vkbd_term;
551static kbd_intr_t	vkbd_intr;
552static kbd_test_if_t	vkbd_test_if;
553static kbd_enable_t	vkbd_enable;
554static kbd_disable_t	vkbd_disable;
555static kbd_read_t	vkbd_read;
556static kbd_check_t	vkbd_check;
557static kbd_read_char_t	vkbd_read_char;
558static kbd_check_char_t	vkbd_check_char;
559static kbd_ioctl_t	vkbd_ioctl;
560static kbd_lock_t	vkbd_lock;
561static void		vkbd_clear_state_locked(vkbd_state_t *state);
562static kbd_clear_state_t vkbd_clear_state;
563static kbd_get_state_t	vkbd_get_state;
564static kbd_set_state_t	vkbd_set_state;
565static kbd_poll_mode_t	vkbd_poll;
566
567static 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
589static int	typematic(int delay, int rate);
590static int	typematic_delay(int delay);
591static int	typematic_rate(int rate);
592
593/* Return the number of found keyboards */
594static int
595vkbd_configure(int flags)
596{
597	return (1);
598}
599
600/* Detect a keyboard */
601static int
602vkbd_probe(int unit, void *arg, int flags)
603{
604	return (0);
605}
606
607/* Reset and initialize the keyboard (stolen from atkbd.c) */
608static int
609vkbd_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);
685bad:
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 */
704static int
705vkbd_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 */
724static int
725vkbd_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 */
744static int
745vkbd_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
755static int
756vkbd_enable(keyboard_t *kbd)
757{
758	KBD_ACTIVATE(kbd);
759	return (0);
760}
761
762/* Disallow the access to the device */
763static int
764vkbd_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 */
771static int
772vkbd_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 */
788static int
789vkbd_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) */
807static u_int
808vkbd_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
816next_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 */
1068static int
1069vkbd_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) */
1090static int
1091vkbd_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 */
1228static int
1229vkbd_lock(keyboard_t *kbd, int lock)
1230{
1231	return (1); /* XXX */
1232}
1233
1234/* Clear the internal state of the keyboard */
1235static void
1236vkbd_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
1253static void
1254vkbd_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 */
1264static int
1265vkbd_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 */
1276static int
1277vkbd_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 */
1286static int
1287vkbd_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
1309static int delays[] = { 250, 500, 750, 1000 };
1310static 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
1315static int
1316typematic_delay(int i)
1317{
1318	return (delays[(i >> 5) & 3]);
1319}
1320
1321static int
1322typematic_rate(int i)
1323{
1324	return (rates[i & 0x1f]);
1325}
1326
1327static int
1328typematic(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
1352KEYBOARD_DRIVER(vkbd, vkbdsw, vkbd_configure);
1353
1354static int
1355vkbd_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
1383DEV_MODULE(vkbd, vkbd_modevent, NULL);
1384
1385