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