> Date: Tue,  9 Nov 2021 15:43:04 +0000
> From: Klemens Nanni <k...@openbsd.org>
> 
> This populates `systat sensors' with the correct lid status on my
> Pinebook Pro:
> 
>       -gpio-key-lid at mainbus0 not configured
>       -gpio-key-power at mainbus0 not configured
>       +gpiokeys0 at mainbus0: "Lid"
>       +gpiokeys0 at mainbus0: "Power"
> 
> 0/1 <-> closed/open is mapped exactly like acpibtn(4) already does on
> other machines, to maintain consistent user experience across devices.
> 
> Next steps are:
> - hook up lid status with `machdep.lidaction', see acpibtn(4)
> - handle power button -> hook up machdep.pwraction, see acpibtn(4)
> 
> 
> Sort gpio{led,charger,keys} while here.
> 
> Feedback? OK?

ok kettenis@

> diff 83b213946bcaccd148d4a46b6ebda89b120fc778 refs/heads/master
> blob - ab52b74cf7e9895cbcb29532b9898cdaf33e89f3
> blob + 0891a80caf135b983dea282f281d7f6089b52e30
> --- distrib/sets/lists/man/mi
> +++ distrib/sets/lists/man/mi
> @@ -1423,6 +1423,7 @@
>  ./usr/share/man/man4/gpiocharger.4
>  ./usr/share/man/man4/gpiodcf.4
>  ./usr/share/man/man4/gpioiic.4
> +./usr/share/man/man4/gpiokeys.4
>  ./usr/share/man/man4/gpioleds.4
>  ./usr/share/man/man4/gpioow.4
>  ./usr/share/man/man4/graphaudio.4
> blob - c32bc8962cd103da4ed17ad63a2162f63a16e639
> blob + 6057d2a559120ada9f43ae0f5e5e6eb63a514be8
> --- share/man/man4/Makefile
> +++ share/man/man4/Makefile
> @@ -37,7 +37,7 @@ MAN=        aac.4 abcrtc.4 abl.4 ac97.4 acphy.4 acrtc.4 \
>       fuse.4 fxp.4 \
>       gdt.4 gentbi.4 gem.4 gfrtc.4 gif.4 glenv.4 glkgpio.4 gpio.4 \
>       gpiocharger.4 gpiodcf.4 \
> -     gpioiic.4 gpioleds.4 gpioow.4 graphaudio.4 gre.4 gscsio.4 \
> +     gpioiic.4 gpiokeys.4 gpioleds.4 gpioow.4 graphaudio.4 gre.4 gscsio.4 \
>       hds.4 hiclock.4 hidwusb.4 hil.4 hilid.4 hilkbd.4 hilms.4 \
>       hireset.4 hitemp.4 hme.4 hotplug.4 hsq.4 \
>       hvn.4 hvs.4 hyperv.4 \
> blob - /dev/null
> blob + 44c147f04672fa1b72820ebd7692d7efbe17ceae (mode 644)
> --- /dev/null
> +++ share/man/man4/gpiokeys.4
> @@ -0,0 +1,50 @@
> +.\"  $OpenBSD: $
> +.\"
> +.\" Copyright (c) 2021 Klemens Nanni <k...@openbsd.org>
> +.\"
> +.\" Permission to use, copy, modify, and distribute this software for any
> +.\" purpose with or without fee is hereby granted, provided that the above
> +.\" copyright notice and this permission notice appear in all copies.
> +.\"
> +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> +.\"
> +.Dd $Mdocdate: September 02 2021 $
> +.Dt GPIOKEYS 4
> +.Os
> +.Sh NAME
> +.Nm gpiokeys
> +.Nd GPIO keys
> +.Sh SYNOPSIS
> +.Cd "gpiokeys* at fdt?"
> +.Sh DESCRIPTION
> +The
> +.Nm
> +driver handles events triggered by GPIO keys.
> +Currently, only lid status events are supported.
> +.Pp
> +The lid status is set up as a sensor and can be monitored using
> +.Xr sysctl 8
> +or
> +.Xr sensorsd 8 .
> +.Sh SEE ALSO
> +.Xr gpio 4 ,
> +.Xr intro 4 ,
> +.Xr sensorsd 8 ,
> +.Xr sysctl 8
> +.Sh HISTORY
> +The
> +.Nm
> +driver first appeared in
> +.Ox 7.1 .
> +.Sh AUTHORS
> +.An -nosplit
> +The
> +.Nm
> +driver was written by
> +.An Klemens Nanni Aq Mt k...@openbsd.org .
> blob - 809ece860c07df596da208638f2f3facc829cb72
> blob + 0ceac9b6159e5cfe43fc4e601274100df1c40ffa
> --- sys/arch/arm64/conf/GENERIC
> +++ sys/arch/arm64/conf/GENERIC
> @@ -131,8 +131,9 @@ amdgpu*           at pci?
>  drm*         at amdgpu?
>  wsdisplay*   at amdgpu?
>  
> -gpioleds*    at fdt?
>  gpiocharger* at fdt?
> +gpiokeys*    at fdt?
> +gpioleds*    at fdt?
>  
>  # Apple
>  apldart*     at fdt?
> blob - 301500e9b0c6501be4d55feb5135ca223d6337cc
> blob + 3d73e22edf7802172b29a26cb8b503eaeb8f3aa9
> --- sys/dev/fdt/files.fdt
> +++ sys/dev/fdt/files.fdt
> @@ -589,10 +589,14 @@ device  dapmic
>  attach       dapmic at i2c
>  file dev/fdt/dapmic.c                dapmic
>  
> -device       gpioleds
> -attach       gpioleds at fdt
> -file dev/fdt/gpioleds.c              gpioleds
> -
>  device       gpiocharger
>  attach       gpiocharger at fdt
>  file dev/fdt/gpiocharger.c           gpiocharger
> +
> +device       gpioleds
> +attach       gpioleds at fdt
> +file dev/fdt/gpioleds.c              gpioleds
> +
> +device       gpiokeys
> +attach       gpiokeys at fdt
> +file dev/fdt/gpiokeys.c              gpiokeys
> blob - /dev/null
> blob + 4b4ca55a5c825ad8d66fbc8ec198bbcd13352b7c (mode 644)
> --- /dev/null
> +++ sys/dev/fdt/gpiokeys.c
> @@ -0,0 +1,179 @@
> +/*   $OpenBSD: $     */
> +/*
> + * Copyright (c) 2021 Klemens Nanni <k...@openbsd.org>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/param.h>
> +#include <sys/systm.h>
> +#include <sys/device.h>
> +#include <sys/gpio.h>
> +#include <sys/malloc.h>
> +#include <sys/queue.h>
> +
> +#include <machine/bus.h>
> +#include <machine/fdt.h>
> +
> +#include <dev/gpio/gpiovar.h>
> +#include <dev/ofw/ofw_gpio.h>
> +#include <dev/ofw/ofw_pinctrl.h>
> +#include <dev/ofw/openfirm.h>
> +#include <dev/ofw/fdt.h>
> +
> +#include <sys/sensors.h>
> +
> +#define      DEVNAME(_s)     ((_s)->sc_dev.dv_xname)
> +
> +/*
> + * Defines from Linux, see:
> + *   Documentation/input/event-codes.rst
> + *   include/dt-bindings/input/linux-event-codes.h
> + */
> +enum gpiokeys_event_type {
> +     GPIOKEYS_EV_KEY = 1,
> +     GPIOKEYS_EV_SW = 5,
> +};
> +
> +enum gpiokeys_switch_event {
> +     GPIOKEYS_SW_LID = 0,    /* set = lid closed */
> +};
> +
> +struct gpiokeys_key {
> +     uint32_t                        *key_pin;
> +     uint32_t                         key_input_type;
> +     uint32_t                         key_code;
> +     struct ksensor                   key_sensor;
> +     SLIST_ENTRY(gpiokeys_key)        entries;
> +};
> +
> +struct gpiokeys_softc {
> +     struct device                    sc_dev;
> +     int                              sc_node;
> +     struct ksensordev                sc_sensordev;
> +     SLIST_HEAD(, gpiokeys_key)       sc_keys;
> +};
> +
> +int   gpiokeys_match(struct device *, void *, void *);
> +void  gpiokeys_attach(struct device *, struct device *, void *);
> +
> +const struct cfattach gpiokeys_ca = {
> +     sizeof (struct gpiokeys_softc), gpiokeys_match, gpiokeys_attach
> +};
> +
> +struct cfdriver gpiokeys_cd = {
> +     NULL, "gpiokeys", DV_DULL
> +};
> +
> +void  gpiokeys_update_key(void *);
> +
> +int
> +gpiokeys_match(struct device *parent, void *match, void *aux)
> +{
> +     const struct fdt_attach_args    *faa = aux;
> +
> +     return OF_is_compatible(faa->fa_node, "gpio-keys") ||
> +         OF_is_compatible(faa->fa_node, "gpio-keys-polled");
> +}
> +
> +void
> +gpiokeys_attach(struct device *parent, struct device *self, void *aux)
> +{
> +     struct gpiokeys_softc   *sc = (struct gpiokeys_softc *)self;
> +     struct fdt_attach_args  *faa = aux;
> +     struct gpiokeys_key     *key;
> +     char                    *label;
> +     uint32_t                 code;
> +     int                      node, len, gpios_len, have_sensors = 0;
> +
> +     SLIST_INIT(&sc->sc_keys);
> +
> +     pinctrl_byname(faa->fa_node, "default");
> +
> +     for (node = OF_child(faa->fa_node); node; node = OF_peer(node)) {
> +             if (OF_getprop(node, "linux,code", &code, sizeof(code)) == -1)
> +                     continue;
> +             gpios_len = OF_getproplen(node, "gpios");
> +             if (gpios_len <= 0)
> +                     continue;
> +             len = OF_getproplen(node, "label");
> +             if (len <= 0)
> +                     continue;
> +             label = malloc(len, M_TEMP, M_WAITOK);
> +             if (OF_getprop(node, "label", label, len) != len) {
> +                     free(label, M_TEMP, len);
> +                     continue;
> +             }
> +             key = malloc(sizeof(*key), M_DEVBUF, M_WAITOK | M_ZERO);
> +             key->key_input_type = OF_getpropint(node, "linux,input-type",
> +                 GPIOKEYS_EV_KEY);
> +             key->key_code = code;
> +             key->key_pin = malloc(gpios_len, M_DEVBUF, M_WAITOK);
> +             OF_getpropintarray(node, "gpios", key->key_pin, gpios_len);
> +             gpio_controller_config_pin(key->key_pin, GPIO_CONFIG_INPUT);
> +
> +             switch (key->key_input_type) {
> +             case GPIOKEYS_EV_SW:
> +                     switch (key->key_code) {
> +                     case GPIOKEYS_SW_LID:
> +                             strlcpy(key->key_sensor.desc, "lid open",
> +                                 sizeof(key->key_sensor.desc));
> +                             key->key_sensor.type = SENSOR_INDICATOR;
> +                             sensor_attach(&sc->sc_sensordev, 
> &key->key_sensor);
> +                             sensor_task_register(key, gpiokeys_update_key, 
> 1);
> +                             have_sensors = 1;
> +                             break;
> +                     }
> +                     break;
> +             }
> +
> +             printf("%s \"%s\"", SLIST_EMPTY(&sc->sc_keys) ? ":" : ",",
> +                 label);
> +             free(label, M_TEMP, len);
> +
> +             SLIST_INSERT_HEAD(&sc->sc_keys, key, entries);
> +     }
> +
> +     if (have_sensors) {
> +             strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
> +                 sizeof(sc->sc_sensordev.xname));
> +             sensordev_install(&sc->sc_sensordev);
> +     }
> +
> +     if (SLIST_EMPTY(&sc->sc_keys))
> +             printf(": no keys");
> +     printf("\n");
> +}
> +
> +void
> +gpiokeys_update_key(void *arg)
> +{
> +     struct gpiokeys_key     *key = arg;
> +     int                      val;
> +
> +     val = gpio_controller_get_pin(key->key_pin);
> +
> +     switch (key->key_input_type) {
> +     case GPIOKEYS_EV_SW:
> +             switch (key->key_code) {
> +             case GPIOKEYS_SW_LID:
> +                     /*
> +                      * Match acpibtn(4), i.e. closed ThinkPad lid yields
> +                      * hw.sensors.acpibtn1.indicator0=Off (lid open)
> +                      */
> +                     key->key_sensor.value = !val;
> +                     break;
> +             }
> +             break;
> +     }
> +}
> 
> 

Reply via email to