> 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 > >
