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