]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/hyperv/input/hv_kbd.c
ZFS: MFV 2.0-rc1-ga00c61
[FreeBSD/FreeBSD.git] / sys / dev / hyperv / input / hv_kbd.c
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$");
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 */
80 static int
81 hvkbd_configure(int flags)
82 {
83         return (0);
84 }
85
86 /* detect a keyboard, not used */
87 static int
88 hvkbd_probe(int unit, void *arg, int flags)
89 {
90         return (ENXIO);
91 }
92
93 /* reset and initialize the device, not used */
94 static int
95 hvkbd_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 */
102 static int
103 hvkbd_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 */
110 static int
111 hvkbd_term(keyboard_t *kbd)
112 {
113         DEBUG_HVKBD(kbd, "%s\n", __func__);
114         return (ENXIO);
115 }
116
117 /* keyboard interrupt routine, not used */
118 static int
119 hvkbd_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 */
126 static int
127 hvkbd_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 */
134 static int
135 hvkbd_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 */
142 static int
143 hvkbd_set_state(keyboard_t *kbd, void *buf, size_t len)
144 {
145         DEBUG_HVKBD(kbd, "%s\n", __func__);
146         return (EINVAL);
147 }
148
149 static int
150 hvkbd_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  */
177 static int
178 hvkbd_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 */
187 static int
188 hvkbd_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
197 static void
198 hvkbd_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. */
209 static int
210 hvkbd_check(keyboard_t *kbd)
211 {
212         DEBUG_HVKBD(kbd, "%s\n", __func__);
213         return (0);
214 }
215
216 /* check if char is waiting */
217 static int
218 hvkbd_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
233 static int
234 hvkbd_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 */
246 static uint32_t
247 hvkbd_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. */
306 static uint32_t
307 hvkbd_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 */
319 static void
320 hvkbd_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
327 static int
328 hvkbd_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 */
425 static int
426 hvkbd_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. */
438 static int
439 hvkbd_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
448 static keyboard_switch_t hvkbdsw = {
449         .probe =        hvkbd_probe,            /* not used */
450         .init =         hvkbd_init,
451         .term =         hvkbd_term,             /* not used */
452         .intr =         hvkbd_intr,             /* not used */
453         .test_if =      hvkbd_test_if,          /* not used */
454         .enable =       hvkbd_enable,
455         .disable =      hvkbd_disable,
456         .read =         hvkbd_read,
457         .check =        hvkbd_check,
458         .read_char =    hvkbd_read_char,
459         .check_char =   hvkbd_check_char,
460         .ioctl =        hvkbd_ioctl,
461         .lock =         hvkbd_lock,             /* not used */
462         .clear_state =  hvkbd_clear_state,
463         .get_state =    hvkbd_get_state,        /* not used */
464         .set_state =    hvkbd_set_state,        /* not used */
465         .poll =         hvkbd_poll,
466 };
467
468 KEYBOARD_DRIVER(hvkbd, hvkbdsw, hvkbd_configure);
469
470 void
471 hv_kbd_intr(hv_kbd_sc *sc)
472 {
473         uint32_t c;
474         if ((sc->sc_flags & HVKBD_FLAG_POLLING) != 0)
475                 return;
476
477         if (KBD_IS_ACTIVE(&sc->sc_kbd) &&
478             KBD_IS_BUSY(&sc->sc_kbd)) {
479                 /* let the callback function process the input */
480                 (sc->sc_kbd.kb_callback.kc_func) (&sc->sc_kbd, KBDIO_KEYINPUT,
481                     sc->sc_kbd.kb_callback.kc_arg);
482         } else {
483                 /* read and discard the input, no one is waiting for it */
484                 do {
485                         c = hvkbd_read_char(&sc->sc_kbd, 0);
486                 } while (c != NOKEY);
487         }
488 }
489
490 int
491 hvkbd_driver_load(module_t mod, int what, void *arg)
492 {
493         switch (what) {
494         case MOD_LOAD:
495                 kbd_add_driver(&hvkbd_kbd_driver);
496                 break;
497         case MOD_UNLOAD:
498                 kbd_delete_driver(&hvkbd_kbd_driver);
499                 break;
500         }
501         return (0);
502 }
503
504 int
505 hv_kbd_drv_attach(device_t dev)
506 {
507         hv_kbd_sc *sc = device_get_softc(dev);
508         int unit = device_get_unit(dev);
509         keyboard_t *kbd = &sc->sc_kbd;
510         keyboard_switch_t *sw;
511         sw = kbd_get_switch(HVKBD_DRIVER_NAME);
512         if (sw == NULL) {
513                 return (ENXIO);
514         }
515
516         kbd_init_struct(kbd, HVKBD_DRIVER_NAME, KB_OTHER, unit, 0, 0, 0);
517         kbd->kb_data = (void *)sc;
518         kbd_set_maps(kbd, &key_map, &accent_map, fkey_tab, nitems(fkey_tab));
519         KBD_FOUND_DEVICE(kbd);
520         hvkbd_clear_state(kbd);
521         KBD_PROBE_DONE(kbd);
522         KBD_INIT_DONE(kbd);
523         sc->sc_mode = K_RAW;
524         (*sw->enable)(kbd);
525
526         if (kbd_register(kbd) < 0) {
527                 goto detach;
528         }
529         KBD_CONFIG_DONE(kbd);
530 #ifdef KBD_INSTALL_CDEV
531         if (kbd_attach(kbd)) {
532                 goto detach;
533         }
534 #endif
535         if (bootverbose) {
536                 kbdd_diag(kbd, bootverbose);
537         }
538         return (0);
539 detach:
540         hv_kbd_drv_detach(dev);
541         return (ENXIO);
542 }
543
544 int
545 hv_kbd_drv_detach(device_t dev)
546 {
547         int error = 0;
548         hv_kbd_sc *sc = device_get_softc(dev);
549         hvkbd_disable(&sc->sc_kbd);
550         if (KBD_IS_CONFIGURED(&sc->sc_kbd)) {
551                 error = kbd_unregister(&sc->sc_kbd);
552                 if (error) {
553                         device_printf(dev, "WARNING: kbd_unregister() "
554                             "returned non-zero! (ignored)\n");
555                 }
556         }
557 #ifdef KBD_INSTALL_CDEV
558         error = kbd_detach(&sc->sc_kbd);
559 #endif
560         return (error);
561 }
562