The branch main has been updated by wulf:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=c2a159286c7694306fde8c161af47a220e1a76f2

commit c2a159286c7694306fde8c161af47a220e1a76f2
Author:     Vladimir Kondratyev <w...@freebsd.org>
AuthorDate: 2021-04-11 23:07:35 +0000
Commit:     Vladimir Kondratyev <w...@freebsd.org>
CommitDate: 2021-04-11 23:14:12 +0000

    hv_kbd: Add evdev protocol support for gen 2 VMs
    
    Reviewed by:    whu
    MFC after:      1 month
    Differential revision:  https://reviews.freebsd.org/D28170
---
 sys/dev/hyperv/input/hv_kbd.c  | 82 ++++++++++++++++++++++++++++++++++++++++++
 sys/dev/hyperv/input/hv_kbdc.h | 13 ++++++-
 2 files changed, 94 insertions(+), 1 deletion(-)

diff --git a/sys/dev/hyperv/input/hv_kbd.c b/sys/dev/hyperv/input/hv_kbd.c
index 3be18da0efef..b1b0760ba13c 100644
--- a/sys/dev/hyperv/input/hv_kbd.c
+++ b/sys/dev/hyperv/input/hv_kbd.c
@@ -27,6 +27,8 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_evdev.h"
+
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/conf.h>
@@ -56,6 +58,11 @@ __FBSDID("$FreeBSD$");
 #include <dev/kbd/kbdreg.h>
 #include <dev/kbd/kbdtables.h>
 
+#ifdef EVDEV_SUPPORT
+#include <dev/evdev/evdev.h>
+#include <dev/evdev/input.h>
+#endif
+
 #include "dev/hyperv/input/hv_kbdc.h"
 
 #define HVKBD_MTX_LOCK(_m) do {                \
@@ -76,6 +83,14 @@ __FBSDID("$FreeBSD$");
 
 #define HVKBD_FLAG_POLLING     0x00000002
 
+#ifdef EVDEV_SUPPORT
+static evdev_event_t hvkbd_ev_event;
+
+static const struct evdev_methods hvkbd_evdev_methods = {
+       .ev_event = hvkbd_ev_event,
+};
+#endif
+
 /* early keyboard probe, not supported */
 static int
 hvkbd_configure(int flags)
@@ -249,6 +264,9 @@ hvkbd_read_char_locked(keyboard_t *kbd, int wait)
        uint32_t scancode = NOKEY;
        keystroke ks;
        hv_kbd_sc *sc = kbd->kb_data;
+#ifdef EVDEV_SUPPORT
+       int keycode;
+#endif
        HVKBD_LOCK_ASSERT();
 
        if (!KBD_IS_ACTIVE(kbd) || !hv_kbd_prod_is_ready(sc))
@@ -293,6 +311,20 @@ hvkbd_read_char_locked(keyboard_t *kbd, int wait)
                        }
                        hv_kbd_remove_top(sc);
                }
+#ifdef EVDEV_SUPPORT
+               /* push evdev event */
+               if (evdev_rcpt_mask & EVDEV_RCPT_HW_KBD &&
+                   sc->ks_evdev != NULL) {
+                       keycode = evdev_scancode2key(&sc->ks_evdev_state,
+                           scancode);
+
+                       if (keycode != KEY_RESERVED) {
+                               evdev_push_event(sc->ks_evdev, EV_KEY,
+                                   (uint16_t)keycode, scancode & 0x80 ? 0 : 1);
+                               evdev_sync(sc->ks_evdev);
+                       }
+               }
+#endif
        } else {
                if (bootverbose)
                        device_printf(sc->dev, "Unsupported mode: %d\n", 
sc->sc_mode);
@@ -413,6 +445,12 @@ hvkbd_ioctl_locked(keyboard_t *kbd, u_long cmd, caddr_t 
arg)
                        DEBUG_HVSC(sc, "setled 0x%x\n", *(int *)arg);
                }
 
+#ifdef EVDEV_SUPPORT
+               /* push LED states to evdev */
+               if (sc->ks_evdev != NULL &&
+                   evdev_rcpt_mask & EVDEV_RCPT_HW_KBD)
+                       evdev_push_leds(sc->ks_evdev, *(int *)arg);
+#endif
                KBD_LED_VAL(kbd) = *(int *)arg;
                break;
        default:
@@ -445,6 +483,22 @@ hvkbd_read(keyboard_t *kbd, int wait)
        return hvkbd_read_char_locked(kbd, wait);
 }
 
+#ifdef EVDEV_SUPPORT
+static void
+hvkbd_ev_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
+    int32_t value)
+{
+       keyboard_t *kbd = evdev_get_softc(evdev);
+
+       if (evdev_rcpt_mask & EVDEV_RCPT_HW_KBD &&
+       (type == EV_LED || type == EV_REP)) {
+               mtx_lock(&Giant);
+               kbd_ev_event(kbd, type, code, value);
+               mtx_unlock(&Giant);
+       }
+}
+#endif
+
 static keyboard_switch_t hvkbdsw = {
        .probe =        hvkbd_probe,            /* not used */
        .init =         hvkbd_init,
@@ -508,6 +562,10 @@ hv_kbd_drv_attach(device_t dev)
        int unit = device_get_unit(dev);
        keyboard_t *kbd = &sc->sc_kbd;
        keyboard_switch_t *sw;
+#ifdef EVDEV_SUPPORT
+       struct evdev_dev *evdev;
+#endif
+
        sw = kbd_get_switch(HVKBD_DRIVER_NAME);
        if (sw == NULL) {
                return (ENXIO);
@@ -523,6 +581,27 @@ hv_kbd_drv_attach(device_t dev)
        sc->sc_mode = K_RAW;
        (*sw->enable)(kbd);
 
+#ifdef EVDEV_SUPPORT
+       evdev = evdev_alloc();
+       evdev_set_name(evdev, "Hyper-V keyboard");
+       evdev_set_phys(evdev, device_get_nameunit(dev));
+       evdev_set_id(evdev, BUS_VIRTUAL, 0, 0, 0);
+       evdev_set_methods(evdev, kbd, &hvkbd_evdev_methods);
+       evdev_support_event(evdev, EV_SYN);
+       evdev_support_event(evdev, EV_KEY);
+       evdev_support_event(evdev, EV_LED);
+       evdev_support_event(evdev, EV_REP);
+       evdev_support_all_known_keys(evdev);
+       evdev_support_led(evdev, LED_NUML);
+       evdev_support_led(evdev, LED_CAPSL);
+       evdev_support_led(evdev, LED_SCROLLL);
+       if (evdev_register_mtx(evdev, &Giant))
+               evdev_free(evdev);
+       else
+               sc->ks_evdev = evdev;
+       sc->ks_evdev_state = 0;
+#endif
+
        if (kbd_register(kbd) < 0) {
                goto detach;
        }
@@ -547,6 +626,9 @@ hv_kbd_drv_detach(device_t dev)
        int error = 0;
        hv_kbd_sc *sc = device_get_softc(dev);
        hvkbd_disable(&sc->sc_kbd);
+#ifdef EVDEV_SUPPORT
+       evdev_free(sc->ks_evdev);
+#endif
        if (KBD_IS_CONFIGURED(&sc->sc_kbd)) {
                error = kbd_unregister(&sc->sc_kbd);
                if (error) {
diff --git a/sys/dev/hyperv/input/hv_kbdc.h b/sys/dev/hyperv/input/hv_kbdc.h
index 3c7bd2a69de7..562009df9a94 100644
--- a/sys/dev/hyperv/input/hv_kbdc.h
+++ b/sys/dev/hyperv/input/hv_kbdc.h
@@ -23,7 +23,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/hyperv/input/hv_kbdc.h 316515 2017-04-05 05:01:23Z 
sephe $
  */
 
 #ifndef _HV_KBD_H
@@ -36,6 +36,12 @@
 
 #include <dev/kbd/kbdreg.h>
 
+#include "opt_evdev.h"
+#ifdef EVDEV_SUPPORT
+#include <dev/evdev/evdev.h>
+#include <dev/evdev/input.h>
+#endif
+
 #define HVKBD_DRIVER_NAME      "hvkbd"
 #define IS_UNICODE             (1)
 #define IS_BREAK               (2)
@@ -87,6 +93,11 @@ typedef struct hv_kbd_sc_t {
        int                             sc_polling;     /* polling recursion 
count */
        uint32_t                        sc_flags;
        int                             debug;
+
+#ifdef EVDEV_SUPPORT
+       struct evdev_dev                *ks_evdev;
+       int                             ks_evdev_state;
+#endif
 } hv_kbd_sc;
 
 int    hv_kbd_produce_ks(hv_kbd_sc *sc, const keystroke *ks);
_______________________________________________
dev-commits-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "dev-commits-src-all-unsubscr...@freebsd.org"

Reply via email to