Author: avg
Date: Wed Aug 12 09:49:25 2020
New Revision: 364145
URL: https://svnweb.freebsd.org/changeset/base/364145

Log:
  gpiokeys: add evdev support
  
  Only linux,code is supported as it maps 1:1 to evdev key codes.
  No reverse mapping for freebsd,code yet.
  
  Reviewed by:  wulf
  MFC after:    3 weeks
  Differential Revision: https://reviews.freebsd.org/D25940

Modified:
  head/sys/dev/gpio/gpiokeys.c

Modified: head/sys/dev/gpio/gpiokeys.c
==============================================================================
--- head/sys/dev/gpio/gpiokeys.c        Wed Aug 12 09:42:05 2020        
(r364144)
+++ head/sys/dev/gpio/gpiokeys.c        Wed Aug 12 09:49:25 2020        
(r364145)
@@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$");
 
 #include "opt_platform.h"
 #include "opt_kbd.h"
+#include "opt_evdev.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -56,6 +57,11 @@ __FBSDID("$FreeBSD$");
 #include <dev/gpio/gpiobusvar.h>
 #include <dev/gpio/gpiokeys.h>
 
+#ifdef EVDEV_SUPPORT
+#include <dev/evdev/evdev.h>
+#include <dev/evdev/input.h>
+#endif
+
 #define        KBD_DRIVER_NAME "gpiokeys"
 
 #define        GPIOKEYS_LOCK(_sc)              mtx_lock(&(_sc)->sc_mtx)
@@ -99,6 +105,9 @@ struct gpiokey
        struct resource         *irq_res;
        void                    *intr_hl;
        struct mtx              mtx;
+#ifdef EVDEV_SUPPORT
+       uint32_t                evcode;
+#endif
        uint32_t                keycode;
        int                     autorepeat;
        struct callout          debounce_callout;
@@ -115,6 +124,9 @@ struct gpiokeys_softc
        struct gpiokey  *sc_keys;
        int             sc_total_keys;
 
+#ifdef EVDEV_SUPPORT
+       struct evdev_dev        *sc_evdev;
+#endif
        keyboard_t      sc_kbd;
        keymap_t        sc_keymap;
        accentmap_t     sc_accmap;
@@ -171,26 +183,34 @@ gpiokeys_put_key(struct gpiokeys_softc *sc, uint32_t k
 }
 
 static void
-gpiokeys_key_event(struct gpiokeys_softc *sc, uint16_t keycode, int pressed)
+gpiokeys_key_event(struct gpiokeys_softc *sc, struct gpiokey *key, int pressed)
 {
-       uint32_t key;
+       uint32_t code;
 
-
-       key = keycode & SCAN_KEYCODE_MASK;
-
-       if (!pressed)
-               key |= KEY_RELEASE;
-
        GPIOKEYS_LOCK(sc);
-       if (keycode & SCAN_PREFIX_E0)
-               gpiokeys_put_key(sc, 0xe0);
-       else if (keycode & SCAN_PREFIX_E1)
-               gpiokeys_put_key(sc, 0xe1);
+#ifdef EVDEV_SUPPORT
+       if (key->evcode != GPIOKEY_NONE &&
+           (evdev_rcpt_mask & EVDEV_RCPT_HW_KBD) != 0) {
+               evdev_push_key(sc->sc_evdev, key->evcode, pressed);
+               evdev_sync(sc->sc_evdev);
+       }
+#endif
+       if (key->keycode != GPIOKEY_NONE) {
+               code = key->keycode & SCAN_KEYCODE_MASK;
+               if (!pressed)
+                       code |= KEY_RELEASE;
 
-       gpiokeys_put_key(sc, key);
+               if (key->keycode & SCAN_PREFIX_E0)
+                       gpiokeys_put_key(sc, 0xe0);
+               else if (key->keycode & SCAN_PREFIX_E1)
+                       gpiokeys_put_key(sc, 0xe1);
+
+               gpiokeys_put_key(sc, code);
+       }
        GPIOKEYS_UNLOCK(sc);
 
-       gpiokeys_event_keyinput(sc);
+       if (key->keycode != GPIOKEY_NONE)
+               gpiokeys_event_keyinput(sc);
 }
 
 static void
@@ -200,11 +220,8 @@ gpiokey_autorepeat(void *arg)
 
        key = arg;
 
-       if (key->keycode == GPIOKEY_NONE)
-               return;
+       gpiokeys_key_event(key->parent_sc, key, 1);
 
-       gpiokeys_key_event(key->parent_sc, key->keycode, 1);
-
        callout_reset(&key->repeat_callout, key->repeat,
                    gpiokey_autorepeat, key);
 }
@@ -217,12 +234,9 @@ gpiokey_debounced_intr(void *arg)
 
        key = arg;
 
-       if (key->keycode == GPIOKEY_NONE)
-               return;
-
        gpio_pin_is_active(key->pin, &active);
        if (active) {
-               gpiokeys_key_event(key->parent_sc, key->keycode, 1);
+               gpiokeys_key_event(key->parent_sc, key, 1);
                if (key->autorepeat) {
                        callout_reset(&key->repeat_callout, key->repeat_delay,
                            gpiokey_autorepeat, key);
@@ -232,7 +246,7 @@ gpiokey_debounced_intr(void *arg)
                if (key->autorepeat &&
                    callout_pending(&key->repeat_callout))
                        callout_stop(&key->repeat_callout);
-               gpiokeys_key_event(key->parent_sc, key->keycode, 0);
+               gpiokeys_key_event(key->parent_sc, key, 0);
        }
 }
 
@@ -301,6 +315,10 @@ gpiokeys_attach_key(struct gpiokeys_softc *sc, phandle
                if (key->keycode == GPIOKEY_NONE)
                        device_printf(sc->sc_dev, "<%s> failed to map 
linux,code value 0x%x\n",
                            key_name, code);
+#ifdef EVDEV_SUPPORT
+               key->evcode = code;
+               evdev_support_key(sc->sc_evdev, code);
+#endif
        }
        else
                device_printf(sc->sc_dev, "<%s> no linux,code or freebsd,code 
property\n",
@@ -365,7 +383,6 @@ gpiokeys_detach_key(struct gpiokeys_softc *sc, struct 
        if (key->pin)
                gpio_pin_release(key->pin);
        GPIOKEY_UNLOCK(key);
-
        GPIOKEY_LOCK_DESTROY(key);
 }
 
@@ -383,11 +400,14 @@ gpiokeys_probe(device_t dev)
 static int
 gpiokeys_attach(device_t dev)
 {
-       int unit;
        struct gpiokeys_softc *sc;
        keyboard_t *kbd;
+#ifdef EVDEV_SUPPORT
+       char *name;
+#endif
        phandle_t keys, child;
        int total_keys;
+       int unit;
 
        if ((keys = ofw_bus_get_node(dev)) == -1)
                return (ENXIO);
@@ -435,6 +455,19 @@ gpiokeys_attach(device_t dev)
                kbdd_diag(kbd, 1);
        }
 
+#ifdef EVDEV_SUPPORT
+       sc->sc_evdev = evdev_alloc();
+       evdev_set_name(sc->sc_evdev, device_get_desc(dev));
+
+       OF_getprop_alloc(keys, "name", (void **)&name);
+       evdev_set_phys(sc->sc_evdev, name != NULL ? name : "unknown");
+       OF_prop_free(name);
+
+       evdev_set_id(sc->sc_evdev, BUS_VIRTUAL, 0, 0, 0);
+       evdev_support_event(sc->sc_evdev, EV_SYN);
+       evdev_support_event(sc->sc_evdev, EV_KEY);
+#endif
+
        total_keys = 0;
 
        /* Traverse the 'gpio-keys' node and count keys */
@@ -458,6 +491,13 @@ gpiokeys_attach(device_t dev)
                }
        }
 
+#ifdef EVDEV_SUPPORT
+       if (evdev_register_mtx(sc->sc_evdev, &sc->sc_mtx) != 0) {
+               device_printf(dev, "failed to register evdev device\n");
+               goto detach;
+       }
+#endif
+
        return (0);
 
 detach:
@@ -484,6 +524,10 @@ gpiokeys_detach(device_t dev)
        kbd_detach(kbd);
 #endif
        kbd_unregister(kbd);
+
+#ifdef EVDEV_SUPPORT
+       evdev_free(sc->sc_evdev);
+#endif
 
        GPIOKEYS_LOCK_DESTROY(sc);
        if (sc->sc_keys)
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to