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