1/*-
2 * Copyright (c) 2017 Microsoft Corp.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice unmodified, this list of conditions, and the following
10 *    disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: stable/10/sys/dev/hyperv/input/hv_kbd.c 317823 2017-05-05 06:00:32Z sephe $");
29
30#include <sys/param.h>
31#include <sys/kernel.h>
32#include <sys/conf.h>
33#include <sys/uio.h>
34#include <sys/bus.h>
35#include <sys/malloc.h>
36#include <sys/mbuf.h>
37#include <sys/module.h>
38#include <sys/lock.h>
39#include <sys/taskqueue.h>
40#include <sys/selinfo.h>
41#include <sys/sysctl.h>
42#include <sys/poll.h>
43#include <sys/proc.h>
44#include <sys/queue.h>
45#include <sys/kthread.h>
46#include <sys/syscallsubr.h>
47#include <sys/sysproto.h>
48#include <sys/sema.h>
49#include <sys/signal.h>
50#include <sys/syslog.h>
51#include <sys/systm.h>
52#include <sys/mutex.h>
53#include <sys/callout.h>
54
55#include <sys/kbio.h>
56#include <dev/kbd/kbdreg.h>
57#include <dev/kbd/kbdtables.h>
58
59#include "dev/hyperv/input/hv_kbdc.h"
60
61#define HVKBD_MTX_LOCK(_m) do {		\
62	mtx_lock(_m);			\
63} while (0)
64
65#define HVKBD_MTX_UNLOCK(_m) do {	\
66	mtx_unlock(_m);			\
67} while (0)
68
69#define HVKBD_MTX_ASSERT(_m, _t) do {	\
70	mtx_assert(_m, _t);		\
71} while (0)
72
73#define	HVKBD_LOCK()		HVKBD_MTX_LOCK(&Giant)
74#define	HVKBD_UNLOCK()		HVKBD_MTX_UNLOCK(&Giant)
75#define	HVKBD_LOCK_ASSERT()	HVKBD_MTX_ASSERT(&Giant, MA_OWNED)
76
77#define HVKBD_FLAG_POLLING	0x00000002
78
79/* early keyboard probe, not supported */
80static int
81hvkbd_configure(int flags)
82{
83	return (0);
84}
85
86/* detect a keyboard, not used */
87static int
88hvkbd_probe(int unit, void *arg, int flags)
89{
90	return (ENXIO);
91}
92
93/* reset and initialize the device, not used */
94static int
95hvkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
96{
97	DEBUG_HVKBD(*kbdp, "%s\n", __func__);
98	return (ENXIO);
99}
100
101/* test the interface to the device, not used */
102static int
103hvkbd_test_if(keyboard_t *kbd)
104{
105	DEBUG_HVKBD(kbd, "%s\n", __func__);
106	return (0);
107}
108
109/* finish using this keyboard, not used */
110static int
111hvkbd_term(keyboard_t *kbd)
112{
113	DEBUG_HVKBD(kbd, "%s\n", __func__);
114	return (ENXIO);
115}
116
117/* keyboard interrupt routine, not used */
118static int
119hvkbd_intr(keyboard_t *kbd, void *arg)
120{
121	DEBUG_HVKBD(kbd, "%s\n", __func__);
122	return (0);
123}
124
125/* lock the access to the keyboard, not used */
126static int
127hvkbd_lock(keyboard_t *kbd, int lock)
128{
129	DEBUG_HVKBD(kbd, "%s\n", __func__);
130	return (1);
131}
132
133/* save the internal state, not used */
134static int
135hvkbd_get_state(keyboard_t *kbd, void *buf, size_t len)
136{
137	DEBUG_HVKBD(kbd,"%s\n",  __func__);
138	return (len == 0) ? 1 : -1;
139}
140
141/* set the internal state, not used */
142static int
143hvkbd_set_state(keyboard_t *kbd, void *buf, size_t len)
144{
145	DEBUG_HVKBD(kbd, "%s\n", __func__);
146	return (EINVAL);
147}
148
149static int
150hvkbd_poll(keyboard_t *kbd, int on)
151{
152	hv_kbd_sc *sc = kbd->kb_data;
153
154	HVKBD_LOCK();
155	/*
156	 * Keep a reference count on polling to allow recursive
157	 * cngrab() during a panic for example.
158	 */
159	if (on)
160		sc->sc_polling++;
161	else if (sc->sc_polling > 0)
162		sc->sc_polling--;
163
164	if (sc->sc_polling != 0) {
165		sc->sc_flags |= HVKBD_FLAG_POLLING;
166	} else {
167		sc->sc_flags &= ~HVKBD_FLAG_POLLING;
168	}
169	HVKBD_UNLOCK();
170	return (0);
171}
172
173/*
174 * Enable the access to the device; until this function is called,
175 * the client cannot read from the keyboard.
176 */
177static int
178hvkbd_enable(keyboard_t *kbd)
179{
180	HVKBD_LOCK();
181	KBD_ACTIVATE(kbd);
182	HVKBD_UNLOCK();
183	return (0);
184}
185
186/* disallow the access to the device */
187static int
188hvkbd_disable(keyboard_t *kbd)
189{
190	DEBUG_HVKBD(kbd, "%s\n", __func__);
191	HVKBD_LOCK();
192	KBD_DEACTIVATE(kbd);
193	HVKBD_UNLOCK();
194	return (0);
195}
196
197static void
198hvkbd_do_poll(hv_kbd_sc *sc, uint8_t wait)
199{
200	while (!hv_kbd_prod_is_ready(sc)) {
201		hv_kbd_read_channel(sc->hs_chan, sc);
202		if (!wait)
203			break;
204	}
205}
206
207/* check if data is waiting */
208/* Currently unused. */
209static int
210hvkbd_check(keyboard_t *kbd)
211{
212	DEBUG_HVKBD(kbd, "%s\n", __func__);
213	return (0);
214}
215
216/* check if char is waiting */
217static int
218hvkbd_check_char_locked(keyboard_t *kbd)
219{
220	HVKBD_LOCK_ASSERT();
221	if (!KBD_IS_ACTIVE(kbd))
222		return (FALSE);
223
224	hv_kbd_sc *sc = kbd->kb_data;
225	if (sc->sc_flags & HVKBD_FLAG_POLLING)
226		hvkbd_do_poll(sc, 0);
227	if (hv_kbd_prod_is_ready(sc)) {
228		return (TRUE);
229	}
230	return (FALSE);
231}
232
233static int
234hvkbd_check_char(keyboard_t *kbd)
235{
236	int result;
237
238	HVKBD_LOCK();
239	result = hvkbd_check_char_locked(kbd);
240	HVKBD_UNLOCK();
241
242	return (result);
243}
244
245/* read char from the keyboard */
246static uint32_t
247hvkbd_read_char_locked(keyboard_t *kbd, int wait)
248{
249	uint32_t scancode = NOKEY;
250	keystroke ks;
251	hv_kbd_sc *sc = kbd->kb_data;
252	HVKBD_LOCK_ASSERT();
253
254	if (!KBD_IS_ACTIVE(kbd) || !hv_kbd_prod_is_ready(sc))
255		return (NOKEY);
256	if (sc->sc_mode == K_RAW) {
257		if (hv_kbd_fetch_top(sc, &ks)) {
258			return (NOKEY);
259		}
260		if ((ks.info & IS_E0) || (ks.info & IS_E1)) {
261			/**
262			 * Emulate the generation of E0 or E1 scancode,
263			 * the real scancode will be consumed next time.
264			 */
265			if (ks.info & IS_E0) {
266				scancode = XTKBD_EMUL0;
267				ks.info &= ~IS_E0;
268			} else if (ks.info & IS_E1) {
269				scancode = XTKBD_EMUL1;
270				ks.info &= ~IS_E1;
271			}
272			/**
273			 * Change the top item to avoid encountering
274			 * E0 or E1 twice.
275			 */
276			hv_kbd_modify_top(sc, &ks);
277		} else if (ks.info & IS_UNICODE) {
278			/**
279			 * XXX: Hyperv host send unicode to VM through
280			 * 'Type clipboard text', the mapping from
281			 * unicode to scancode depends on the keymap.
282			 * It is so complicated that we do not plan to
283			 * support it yet.
284			 */
285			if (bootverbose)
286				device_printf(sc->dev, "Unsupported unicode\n");
287			hv_kbd_remove_top(sc);
288			return (NOKEY);
289		} else {
290			scancode = ks.makecode;
291			if (ks.info & IS_BREAK) {
292				scancode |= XTKBD_RELEASE;
293			}
294			hv_kbd_remove_top(sc);
295		}
296	} else {
297		if (bootverbose)
298			device_printf(sc->dev, "Unsupported mode: %d\n", sc->sc_mode);
299	}
300	++kbd->kb_count;
301	DEBUG_HVKBD(kbd, "read scan: 0x%x\n", scancode);
302	return scancode;
303}
304
305/* Currently wait is always false. */
306static uint32_t
307hvkbd_read_char(keyboard_t *kbd, int wait)
308{
309	uint32_t keycode;
310
311	HVKBD_LOCK();
312	keycode = hvkbd_read_char_locked(kbd, wait);
313	HVKBD_UNLOCK();
314
315	return (keycode);
316}
317
318/* clear the internal state of the keyboard */
319static void
320hvkbd_clear_state(keyboard_t *kbd)
321{
322	hv_kbd_sc *sc = kbd->kb_data;
323	sc->sc_state &= LOCK_MASK;	/* preserve locking key state */
324	sc->sc_flags &= ~HVKBD_FLAG_POLLING;
325}
326
327static int
328hvkbd_ioctl_locked(keyboard_t *kbd, u_long cmd, caddr_t arg)
329{
330	int i;
331#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
332    defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
333        int ival;
334#endif
335	hv_kbd_sc *sc = kbd->kb_data;
336	switch (cmd) {
337	case KDGKBMODE:
338		*(int *)arg = sc->sc_mode;
339		break;
340#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
341    defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
342	case _IO('K', 7):
343		ival = IOCPARM_IVAL(arg);
344		arg = (caddr_t)&ival;
345		/* FALLTHROUGH */
346#endif
347	case KDSKBMODE:		/* set keyboard mode */
348		DEBUG_HVKBD(kbd, "expected mode: %x\n", *(int *)arg);
349		switch (*(int *)arg) {
350		case K_XLATE:
351			if (sc->sc_mode != K_XLATE) {
352				/* make lock key state and LED state match */
353				sc->sc_state &= ~LOCK_MASK;
354				sc->sc_state |= KBD_LED_VAL(kbd);
355			}
356			/* FALLTHROUGH */
357		case K_RAW:
358		case K_CODE:
359			if (sc->sc_mode != *(int *)arg) {
360				DEBUG_HVKBD(kbd, "mod changed to %x\n", *(int *)arg);
361				if ((sc->sc_flags & HVKBD_FLAG_POLLING) == 0)
362					hvkbd_clear_state(kbd);
363				sc->sc_mode = *(int *)arg;
364			}
365			break;
366		default:
367			return (EINVAL);
368		}
369		break;
370	case KDGKBSTATE:	/* get lock key state */
371		*(int *)arg = sc->sc_state & LOCK_MASK;
372		break;
373#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
374    defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
375	case _IO('K', 20):
376		ival = IOCPARM_IVAL(arg);
377		arg = (caddr_t)&ival;
378		/* FALLTHROUGH */
379#endif
380	case KDSKBSTATE:		/* set lock key state */
381		if (*(int *)arg & ~LOCK_MASK) {
382			return (EINVAL);
383		}
384		sc->sc_state &= ~LOCK_MASK;
385		sc->sc_state |= *(int *)arg;
386		return hvkbd_ioctl_locked(kbd, KDSETLED, arg);
387	case KDGETLED:			/* get keyboard LED */
388		*(int *)arg = KBD_LED_VAL(kbd);
389		break;
390#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
391    defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
392	case _IO('K', 66):
393		ival = IOCPARM_IVAL(arg);
394		arg = (caddr_t)&ival;
395		/* FALLTHROUGH */
396#endif
397	case KDSETLED:			/* set keyboard LED */
398		/* NOTE: lock key state in "sc_state" won't be changed */
399		if (*(int *)arg & ~LOCK_MASK)
400			return (EINVAL);
401
402		i = *(int *)arg;
403
404		/* replace CAPS LED with ALTGR LED for ALTGR keyboards */
405		if (sc->sc_mode == K_XLATE &&
406		    kbd->kb_keymap->n_keys > ALTGR_OFFSET) {
407			if (i & ALKED)
408				i |= CLKED;
409			else
410				i &= ~CLKED;
411		}
412		if (KBD_HAS_DEVICE(kbd)) {
413			DEBUG_HVSC(sc, "setled 0x%x\n", *(int *)arg);
414		}
415
416		KBD_LED_VAL(kbd) = *(int *)arg;
417		break;
418	default:
419		return (genkbd_commonioctl(kbd, cmd, arg));
420	}
421	return (0);
422}
423
424/* some useful control functions */
425static int
426hvkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
427{
428	DEBUG_HVKBD(kbd, "%s: %lx start\n", __func__, cmd);
429	HVKBD_LOCK();
430	int ret = hvkbd_ioctl_locked(kbd, cmd, arg);
431	HVKBD_UNLOCK();
432	DEBUG_HVKBD(kbd, "%s: %lx end %d\n", __func__, cmd, ret);
433	return (ret);
434}
435
436/* read one byte from the keyboard if it's allowed */
437/* Currently unused. */
438static int
439hvkbd_read(keyboard_t *kbd, int wait)
440{
441	DEBUG_HVKBD(kbd, "%s\n", __func__);
442	HVKBD_LOCK_ASSERT();
443	if (!KBD_IS_ACTIVE(kbd))
444		return (-1);
445	return hvkbd_read_char_locked(kbd, wait);
446}
447
448static keyboard_switch_t hvkbdsw = {
449	hvkbd_probe,		/* not used */
450	hvkbd_init,
451	hvkbd_term,		/* not used */
452	hvkbd_intr,		/* not used */
453	hvkbd_test_if,		/* not used */
454	hvkbd_enable,
455	hvkbd_disable,
456	hvkbd_read,
457	hvkbd_check,
458	hvkbd_read_char,
459	hvkbd_check_char,
460	hvkbd_ioctl,
461	hvkbd_lock,		/* not used */
462	hvkbd_clear_state,
463	hvkbd_get_state,	/* not used */
464	hvkbd_set_state,	/* not used */
465	genkbd_get_fkeystr,
466	hvkbd_poll,
467	genkbd_diag,
468};
469
470KEYBOARD_DRIVER(hvkbd, hvkbdsw, hvkbd_configure);
471
472void
473hv_kbd_intr(hv_kbd_sc *sc)
474{
475	uint32_t c;
476	if ((sc->sc_flags & HVKBD_FLAG_POLLING) != 0)
477		return;
478
479	if (KBD_IS_ACTIVE(&sc->sc_kbd) &&
480	    KBD_IS_BUSY(&sc->sc_kbd)) {
481		/* let the callback function process the input */
482		(sc->sc_kbd.kb_callback.kc_func) (&sc->sc_kbd, KBDIO_KEYINPUT,
483		    sc->sc_kbd.kb_callback.kc_arg);
484	} else {
485		/* read and discard the input, no one is waiting for it */
486		do {
487			c = hvkbd_read_char(&sc->sc_kbd, 0);
488		} while (c != NOKEY);
489	}
490}
491
492int
493hvkbd_driver_load(module_t mod, int what, void *arg)
494{
495	switch (what) {
496	case MOD_LOAD:
497		kbd_add_driver(&hvkbd_kbd_driver);
498		break;
499	case MOD_UNLOAD:
500		kbd_delete_driver(&hvkbd_kbd_driver);
501		break;
502	}
503	return (0);
504}
505
506int
507hv_kbd_drv_attach(device_t dev)
508{
509	hv_kbd_sc *sc = device_get_softc(dev);
510	int unit = device_get_unit(dev);
511	keyboard_t *kbd = &sc->sc_kbd;
512	keyboard_switch_t *sw;
513	sw = kbd_get_switch(HVKBD_DRIVER_NAME);
514	if (sw == NULL) {
515		return (ENXIO);
516	}
517
518	kbd_init_struct(kbd, HVKBD_DRIVER_NAME, KB_OTHER, unit, 0, 0, 0);
519	kbd->kb_data = (void *)sc;
520	kbd_set_maps(kbd, &key_map, &accent_map, fkey_tab, nitems(fkey_tab));
521	KBD_FOUND_DEVICE(kbd);
522	hvkbd_clear_state(kbd);
523	KBD_PROBE_DONE(kbd);
524	KBD_INIT_DONE(kbd);
525	sc->sc_mode = K_RAW;
526	(*sw->enable)(kbd);
527
528	if (kbd_register(kbd) < 0) {
529		goto detach;
530	}
531	KBD_CONFIG_DONE(kbd);
532#ifdef KBD_INSTALL_CDEV
533        if (kbd_attach(kbd)) {
534		goto detach;
535	}
536#endif
537	if (bootverbose) {
538		genkbd_diag(kbd, bootverbose);
539	}
540	return (0);
541detach:
542	hv_kbd_drv_detach(dev);
543	return (ENXIO);
544}
545
546int
547hv_kbd_drv_detach(device_t dev)
548{
549	int error = 0;
550	hv_kbd_sc *sc = device_get_softc(dev);
551	hvkbd_disable(&sc->sc_kbd);
552	if (KBD_IS_CONFIGURED(&sc->sc_kbd)) {
553		error = kbd_unregister(&sc->sc_kbd);
554		if (error) {
555			device_printf(dev, "WARNING: kbd_unregister() "
556			    "returned non-zero! (ignored)\n");
557		}
558	}
559#ifdef KBD_INSTALL_CDEV
560	error = kbd_detach(&sc->sc_kbd);
561#endif
562	return (error);
563}
564
565