> Date: Sat, 30 May 2020 12:26:00 -0500
> From: joshua stein <[email protected]>
> 
> A driver for tablet hardware buttons which seems to be a 
> standardized interface.  Used on the Surface Go.
> 
> When pressing the power button, the driver receives a button down 
> and then a button up event, unlike acpibtn.  Since there may be an 
> opportunity to do something different based on the duration of the 
> button press, it takes over shutdown/suspend from acpibtn(4).

That last bit is a bit surprising.

Are you saying that this machine has an acpibtn(4) as well?  And that
it works if this driver doesn't attach?

In any case, a dmesg + acpidump for this machine would be appreciated
since that would allow me to make a little bit more sense out of this.

> diff --git share/man/man4/Makefile share/man/man4/Makefile
> index 2d9a57d3814..258399f2e7a 100644
> --- share/man/man4/Makefile
> +++ share/man/man4/Makefile
> @@ -3,6 +3,7 @@
>  MAN= aac.4 abcrtc.4 ac97.4 acphy.4 acrtc.4 \
>       acpi.4 acpiac.4 acpials.4 acpiasus.4 acpibat.4 \
>       acpibtn.4 acpicbkbd.4 acpicpu.4 acpidock.4 acpihve.4 acpiec.4 \
> +     acpihid.4 \
>       acpihpet.4 acpimadt.4 acpimcfg.4 acpipci.4 acpiprt.4 acpipwrres.4 \
>       acpisbs.4 acpisony.4 acpisurface.4 acpithinkpad.4 acpitoshiba.4 \
>       acpitimer.4 acpivideo.4 acpivout.4 acpitz.4 \
> diff --git share/man/man4/acpihid.4 share/man/man4/acpihid.4
> new file mode 100644
> index 00000000000..8d54da962d1
> --- /dev/null
> +++ share/man/man4/acpihid.4
> @@ -0,0 +1,47 @@
> +.\"  $OpenBSD$
> +.\"
> +.\" Copyright (c) 2020 joshua stein <[email protected]>
> +.\"
> +.\" 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$
> +.Dt ACPIHID 4
> +.Os
> +.Sh NAME
> +.Nm acpihid
> +.Nd ACPI HID event and 5-button array driver
> +.Sh SYNOPSIS
> +.Cd "acpihid* at acpi?"
> +.Sh DESCRIPTION
> +The
> +.Nm
> +driver supports ACPI HID events and 5-button array devices found on some
> +tablet devices.
> +Power button events are processed according to the
> +.Va machdep.pwraction
> +sysctl value.
> +.Sh SEE ALSO
> +.Xr acpi 4 ,
> +.Xr acpibtn 4 ,
> +.Xr sysctl 8
> +.Sh HISTORY
> +The
> +.Nm
> +driver first appeared in
> +.Ox 6.8 .
> +.Sh AUTHORS
> +.An -nosplit
> +The
> +.Nm
> +driver was written by
> +.An joshua stein Aq Mt [email protected] .
> diff --git sys/arch/amd64/conf/GENERIC sys/arch/amd64/conf/GENERIC
> index 87893bfafea..b77a3b4ead5 100644
> --- sys/arch/amd64/conf/GENERIC
> +++ sys/arch/amd64/conf/GENERIC
> @@ -71,6 +71,7 @@ acpials*    at acpi?
>  tpm*         at acpi?
>  acpihve*     at acpi?
>  acpisurface* at acpi?
> +acpihid*     at acpi?
>  ipmi0                at acpi? disable
>  ccpmic*              at iic?
>  tipmic*              at iic?
> diff --git sys/dev/acpi/acpi.c sys/dev/acpi/acpi.c
> index 7c103347980..306419761c7 100644
> --- sys/dev/acpi/acpi.c
> +++ sys/dev/acpi/acpi.c
> @@ -72,6 +72,7 @@ int acpi_debug = 16;
>  int  acpi_poll_enabled;
>  int  acpi_hasprocfvs;
>  int  acpi_haspci;
> +int  acpi_hashidpower;
>  
>  #define ACPIEN_RETRIES 15
>  
> @@ -2025,6 +2026,9 @@ acpi_pbtn_task(void *arg0, int dummy)
>           en | ACPI_PM1_PWRBTN_EN);
>       splx(s);
>  
> +     if (acpi_hashidpower)
> +             return;
> +
>       switch (pwr_action) {
>       case 0:
>               break;
> diff --git sys/dev/acpi/acpibtn.c sys/dev/acpi/acpibtn.c
> index da3b59ef084..e0b759121ee 100644
> --- sys/dev/acpi/acpibtn.c
> +++ sys/dev/acpi/acpibtn.c
> @@ -270,6 +270,9 @@ sleep:
>  #endif /* SMALL_KERNEL */
>               break;
>       case ACPIBTN_POWER:
> +             if (acpi_hashidpower)
> +                     break;
> +
>               if (notify_type == 0x80) {
>                       switch (pwr_action) {
>                       case 0:
> diff --git sys/dev/acpi/acpihid.c sys/dev/acpi/acpihid.c
> new file mode 100644
> index 00000000000..5ec875a86e8
> --- /dev/null
> +++ sys/dev/acpi/acpihid.c
> @@ -0,0 +1,254 @@
> +/* $OpenBSD$ */
> +/*
> + * ACPI HID event and 5-button array driver
> + *
> + * Copyright (c) 2018 joshua stein <[email protected]>
> + *
> + * 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/signalvar.h>
> +#include <sys/systm.h>
> +#include <sys/device.h>
> +#include <sys/malloc.h>
> +
> +#include <machine/bus.h>
> +#include <machine/apmvar.h>
> +
> +#include <dev/acpi/acpireg.h>
> +#include <dev/acpi/acpivar.h>
> +#include <dev/acpi/acpidev.h>
> +#include <dev/acpi/amltypes.h>
> +#include <dev/acpi/dsdt.h>
> +
> +#include "audio.h"
> +#include "wskbd.h"
> +
> +/* #define ACPIHID_DEBUG */
> +
> +#ifdef ACPIHID_DEBUG
> +#define DPRINTF(x) printf x
> +#else
> +#define DPRINTF(x)
> +#endif
> +
> +struct acpihid_softc {
> +     struct device           sc_dev;
> +
> +     bus_space_tag_t         sc_iot;
> +     bus_space_handle_t      sc_ioh;
> +
> +     struct acpi_softc       *sc_acpi;
> +     struct aml_node         *sc_devnode;
> +     int                     sc_5_button;
> +};
> +
> +int  acpihid_match(struct device *, void *, void *);
> +void acpihid_attach(struct device *, struct device *, void *);
> +int  acpihid_button_array_enable(struct acpihid_softc *, int);
> +int  acpihid_eval(struct acpihid_softc *, char *, uint64_t *);
> +int  acpihid_exec(struct acpihid_softc *, char *, uint64_t);
> +int  acpihid_notify(struct aml_node *, int, void *);
> +
> +#if NAUDIO > 0 && NWSKBD > 0
> +extern int wskbd_set_mixervolume(long, long);
> +#endif
> +
> +extern int acpi_hashidpower;
> +extern int pwr_action;
> +
> +struct cfattach acpihid_ca = {
> +     sizeof(struct acpihid_softc),
> +     acpihid_match,
> +     acpihid_attach,
> +     NULL,
> +     NULL,
> +};
> +
> +struct cfdriver acpihid_cd = {
> +     NULL, "acpihid", DV_DULL
> +};
> +
> +const char *acpihid_hids[] = {
> +     "INT33D5",
> +     NULL
> +};
> +
> +int
> +acpihid_match(struct device *parent, void *match, void *aux)
> +{
> +     struct acpi_attach_args *aa = aux;
> +     struct cfdata           *cf = match;
> +
> +     return (acpi_matchhids(aa, acpihid_hids, cf->cf_driver->cd_name));
> +}
> +
> +void
> +acpihid_attach(struct device *parent, struct device *self, void *aux)
> +{
> +     struct acpihid_softc    *sc = (struct acpihid_softc *)self;
> +     struct acpi_attach_args *aa = aux;
> +     uint64_t                 val, ret;
> +
> +     sc->sc_acpi = (struct acpi_softc *)parent;
> +     sc->sc_devnode = aa->aaa_node;
> +
> +     printf(": %s", sc->sc_devnode->name);
> +
> +     if (acpihid_eval(sc, "HDMM", &val) != 0) {
> +             printf(", failed reading mode\n");
> +             return;
> +     } else if (val != 0) {
> +             printf(", unknown mode %lld\n", val);
> +             return;
> +     }
> +
> +     if (acpihid_eval(sc, "HEBC", &val) == 0 && (val & 0x20000))
> +             sc->sc_5_button = 1;
> +
> +     aml_register_notify(sc->sc_devnode, aa->aaa_dev, acpihid_notify,
> +         sc, ACPIDEV_NOPOLL);
> +
> +     /* enable hid set */
> +     acpihid_exec(sc, "HDSM", 1);
> +
> +     if (sc->sc_5_button) {
> +             acpihid_button_array_enable(sc, 1);
> +
> +             if (acpihid_eval(sc, "BTNL", &ret) == 0) {
> +                     printf(", 5 button array");
> +                     acpi_hashidpower = 1;
> +             } else
> +                     printf(", failed enabling HID power button");
> +     }
> +
> +     printf("\n");
> +}
> +
> +int
> +acpihid_button_array_enable(struct acpihid_softc *sc, int enable)
> +{
> +     int64_t cap;
> +
> +     if (aml_evalinteger(acpi_softc, sc->sc_devnode, "BTNC", 0, NULL,
> +         &cap) != 0) {
> +             printf("%s: failed getting button array capability\n",
> +                 sc->sc_dev.dv_xname);
> +             return 1;
> +     }
> +
> +     if (acpihid_exec(sc, "BTNE", enable ? cap : 1) != 0) {
> +             printf("%s: failed enabling button array\n",
> +                 sc->sc_dev.dv_xname);
> +             return 1;
> +     }
> +
> +     return 0;
> +}
> +
> +int
> +acpihid_eval(struct acpihid_softc *sc, char *method, uint64_t *ret)
> +{
> +     if (aml_evalinteger(acpi_softc, sc->sc_devnode, method, 0, NULL,
> +         ret) != 0) {
> +             printf("%s: eval of %s failed\n", sc->sc_dev.dv_xname, method);
> +             return 1;
> +     }
> +
> +     DPRINTF(("%s: %s = %lld\n", sc->sc_dev.dv_xname, method, *ret));
> +
> +     return 0;
> +}
> +
> +int
> +acpihid_exec(struct acpihid_softc *sc, char *method, uint64_t val)
> +{
> +     struct aml_node *parent;
> +     struct aml_value amlval;
> +
> +     memset(&amlval, 0, sizeof(amlval));
> +     amlval.type = AML_OBJTYPE_INTEGER;
> +     amlval.v_integer = val;
> +
> +     parent = aml_searchname(sc->sc_devnode, method);
> +     if (aml_evalnode(acpi_softc, parent, 1, &amlval, NULL) != 0) {
> +             printf("%s: exec of %s failed\n", sc->sc_dev.dv_xname, method);
> +             return 1;
> +     }
> +
> +     return 0;
> +}
> +
> +int
> +acpihid_notify(struct aml_node *node, int notify_type, void *arg)
> +{
> +     struct acpihid_softc *sc = arg;
> +
> +#ifdef ACPIHID_DEBUG
> +     DPRINTF(("%s: %s: %.2x\n", sc->sc_dev.dv_xname, __func__,
> +         notify_type));
> +#endif
> +     printf("%s: %s: %.2x\n", sc->sc_dev.dv_xname, __func__, notify_type);
> +
> +     switch (notify_type) {
> +     case 0xc2: /* left meta press */
> +             break;
> +     case 0xc3: /* left meta release */
> +             break;
> +     case 0xc4: /* volume up press */
> +#if NAUDIO > 0 && NWSKBD > 0
> +             wskbd_set_mixervolume(1, 1);
> +#endif
> +             break;
> +     case 0xc5: /* volume up release */
> +             break;
> +     case 0xc6: /* volume down press */
> +#if NAUDIO > 0 && NWSKBD > 0
> +             wskbd_set_mixervolume(-1, 1);
> +#endif
> +             break;
> +     case 0xc7: /* volume down release */
> +             break;
> +     case 0xc8: /* rotate lock toggle press */
> +             break;
> +     case 0xc9: /* rotate lock toggle release */
> +             break;
> +     case 0xce: /* power button press */
> +             break;
> +     case 0xcf: /* power button release */
> +             /*
> +              * TODO: time press and release, maybe sleep for a short press
> +              * and power down for long press, disregarding pwr_action?
> +              */
> +             switch (pwr_action) {
> +             case 0:
> +                     break;
> +             case 1:
> +                     acpi_addtask(sc->sc_acpi, acpi_powerdown_task,
> +                         sc->sc_acpi, 0);
> +                     break;
> +             case 2:
> +                     if (acpi_record_event(sc->sc_acpi, 
> APM_USER_SUSPEND_REQ))
> +                             acpi_addtask(sc->sc_acpi, acpi_sleep_task,
> +                                 sc->sc_acpi, ACPI_SLEEP_SUSPEND);
> +                     break;
> +             }
> +             break;
> +     default:
> +             printf("%s: unhandled button 0x%x\n", sc->sc_dev.dv_xname,
> +                 notify_type);
> +     }
> +
> +     return 0;
> +}
> diff --git sys/dev/acpi/acpivar.h sys/dev/acpi/acpivar.h
> index 159b8e7b948..da8a8b128ca 100644
> --- sys/dev/acpi/acpivar.h
> +++ sys/dev/acpi/acpivar.h
> @@ -44,6 +44,7 @@ extern int acpi_debug;
>  
>  extern int acpi_hasprocfvs;
>  extern int acpi_haspci;
> +extern int acpi_hashidpower;
>  
>  struct klist;
>  struct acpiec_softc;
> diff --git sys/dev/acpi/files.acpi sys/dev/acpi/files.acpi
> index 496d7ef1ed1..93e0d21f921 100644
> --- sys/dev/acpi/files.acpi
> +++ sys/dev/acpi/files.acpi
> @@ -216,3 +216,8 @@ file      dev/acpi/amdgpio.c              amdgpio
>  # Broadcom BC7XXX Ethernet controller
>  attach       bse at acpi with bse_acpi
>  file dev/acpi/if_bse_acpi.c          bse_acpi
> +
> +# HID event and 5-button array
> +device       acpihid
> +attach       acpihid at acpi
> +file dev/acpi/acpihid.c              acpihid
> 
> 

Reply via email to