> Date: Tue, 2 Jun 2020 09:00:47 -0500 > From: joshua stein <[email protected]> > > Here is a new revision that tries to call methods through the node's > _DSM first, as it does on Linux. > > It also no longer takes over power button handling as requested by > Mark.
Thanks! ok kettenis@ > acpihid.3 > > diff --git share/man/man4/Makefile share/man/man4/Makefile > index 2cce0a9a132..bb0b6b10068 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/acpi.4 share/man/man4/acpi.4 > index 232d1cd6921..1fba9f5a22d 100644 > --- share/man/man4/acpi.4 > +++ share/man/man4/acpi.4 > @@ -56,6 +56,8 @@ ACPI processor power and performance state > ACPI docking station > .It Xr acpiec 4 > ACPI embedded controller > +.It Xr acpihid 4 > +ACPI HID event and 5-button array > .It Xr acpihpet 4 > ACPI high precision event timer > .It Xr acpihve 4 > diff --git share/man/man4/acpihid.4 share/man/man4/acpihid.4 > new file mode 100644 > index 00000000000..d9914cec7b7 > --- /dev/null > +++ share/man/man4/acpihid.4 > @@ -0,0 +1,42 @@ > +.\" $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 > +.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. > +.Sh SEE ALSO > +.Xr acpi 4 , > +.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 9aa0a390690..618f49fadda 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/acpihid.c sys/dev/acpi/acpihid.c > new file mode 100644 > index 00000000000..063fee1dc21 > --- /dev/null > +++ sys/dev/acpi/acpihid.c > @@ -0,0 +1,401 @@ > +/* $OpenBSD$ */ > +/* > + * ACPI HID event and 5-button array driver > + * > + * Copyright (c) 2018, 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. > + */ > + > +#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 */ > +#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; > + > + /* > + * HEBC v1 > + * 0 - Rotation Lock, Num Lock, Home, End, Page Up, Page Down > + * 1 - Wireless Radio Control > + * 2 - System Power Down > + * 3 - System Hibernate > + * 4 - System Sleep/ System Wake > + * 5 - Scan Next Track > + * 6 - Scan Previous Track > + * 7 - Stop > + * 8 - Play/Pause > + * 9 - Mute > + * 10 - Volume Increment > + * 11 - Volume Decrement > + * 12 - Display Brightness Increment > + * 13 - Display Brightness Decrement > + * 14 - Lock Tablet > + * 15 - Release Tablet > + * 16 - Toggle Bezel > + * 17 - 5 button array > + * 18-31 - reserved > + * > + * HEBC v2 > + * 0-17 - Same as v1 version > + * 18 – Power Button > + * 19 - W Home Button > + * 20 - Volume Up Button > + * 21 - Volume Down Button > + * 22 – Rotation Lock Button > + * 23-31 – reserved > + */ > + uint32_t sc_dsm_fn_mask; > +}; > + > +enum { > + ACPIHID_FUNC_INVALID, > + ACPIHID_FUNC_BTNL, > + ACPIHID_FUNC_HDMM, > + ACPIHID_FUNC_HDSM, > + ACPIHID_FUNC_HDEM, > + ACPIHID_FUNC_BTNS, > + ACPIHID_FUNC_BTNE, > + ACPIHID_FUNC_HEBC_V1, > + ACPIHID_FUNC_VGBS, > + ACPIHID_FUNC_HEBC_V2, > + ACPIHID_FUNC_MAX, > +}; > + > +static const char *acpihid_dsm_funcs[] = { > + NULL, > + "BTNL", > + "HDMM", > + "HDSM", > + "HDEM", > + "BTNS", > + "BTNE", > + "HEBC", > + "VGBS", > + "HEBC", > +}; > + > +int acpihid_match(struct device *, void *, void *); > +void acpihid_attach(struct device *, struct device *, void *); > +void acpihid_init_dsm(struct acpihid_softc *); > +int acpihid_button_array_enable(struct acpihid_softc *, int); > +int acpihid_eval(struct acpihid_softc *, int, int64_t, int64_t *); > +int acpihid_notify(struct aml_node *, int, void *); > + > +#if NAUDIO > 0 && NWSKBD > 0 > +extern int wskbd_set_mixervolume(long, long); > +#endif > + > +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 > +}; > + > +/* eeec56b3-4442-408f-a792-4edd4d758054 */ > +static uint8_t acpihid_guid[] = { > + 0xB3, 0x56, 0xEC, 0xEE, 0x42, 0x44, 0x8F, 0x40, > + 0xA7, 0x92, 0x4E, 0xDD, 0x4D, 0x75, 0x80, 0x54, > +}; > + > +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; > + > + sc->sc_acpi = (struct acpi_softc *)parent; > + sc->sc_devnode = aa->aaa_node; > + > + printf(": %s", sc->sc_devnode->name); > + > + acpihid_init_dsm(sc); > + > + if (acpihid_eval(sc, ACPIHID_FUNC_HDMM, 0, &val) != 0) { > + printf(", failed reading mode\n"); > + return; > + } else if (val != 0) { > + printf(", unknown mode %lld\n", val); > + return; > + } > + > + if ((acpihid_eval(sc, ACPIHID_FUNC_HEBC_V2, 0, &val) == 0 && > + (val & 0x60000)) || > + (acpihid_eval(sc, ACPIHID_FUNC_HEBC_V1, 0, &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_eval(sc, ACPIHID_FUNC_HDSM, 1, NULL); > + > + if (sc->sc_5_button) { > + acpihid_button_array_enable(sc, 1); > + > + if (acpihid_eval(sc, ACPIHID_FUNC_BTNL, 0, NULL) == 0) > + printf(", 5 button array"); > + else > + printf(", failed enabling HID power button"); > + } > + > + printf("\n"); > +} > + > +void > +acpihid_init_dsm(struct acpihid_softc *sc) > +{ > + struct aml_value cmd[4], res; > + > + sc->sc_dsm_fn_mask = 0; > + > + if (!aml_searchname(sc->sc_devnode, "_DSM")) { > + DPRINTF(("%s: no _DSM support\n", sc->sc_dev.dv_xname)); > + return; > + } > + > + bzero(&cmd, sizeof(cmd)); > + cmd[0].type = AML_OBJTYPE_BUFFER; > + cmd[0].v_buffer = (uint8_t *)&acpihid_guid; > + cmd[0].length = sizeof(acpihid_guid); > + /* rev */ > + cmd[1].type = AML_OBJTYPE_INTEGER; > + cmd[1].v_integer = 1; > + cmd[1].length = 1; > + /* func */ > + cmd[2].type = AML_OBJTYPE_INTEGER; > + cmd[2].v_integer = 0; > + cmd[2].length = 1; > + /* not used */ > + cmd[3].type = AML_OBJTYPE_BUFFER; > + cmd[3].length = 0; > + > + if (aml_evalname(acpi_softc, sc->sc_devnode, "_DSM", 4, cmd, > + &res)) { > + printf("%s: eval of _DSM at %s failed\n", > + sc->sc_dev.dv_xname, aml_nodename(sc->sc_devnode)); > + return; > + } > + > + if (res.type != AML_OBJTYPE_BUFFER) { > + printf("%s: bad _DSM result at %s: %d\n", sc->sc_dev.dv_xname, > + aml_nodename(sc->sc_devnode), res.type); > + aml_freevalue(&res); > + return; > + } > + > + sc->sc_dsm_fn_mask = *res.v_buffer; > + DPRINTF(("%s: _DSM function mask 0x%x\n", sc->sc_dev.dv_xname, > + sc->sc_dsm_fn_mask)); > + > + aml_freevalue(&res); > +} > + > +int > +acpihid_eval(struct acpihid_softc *sc, int idx, int64_t arg, int64_t *ret) > +{ > + struct aml_value cmd[4], pkg, *ppkg; > + int64_t tret; > + const char *dsm_func; > + > + if (idx <= ACPIHID_FUNC_INVALID || idx >= ACPIHID_FUNC_MAX) { > + printf("%s: _DSM func index %d out of bounds\n", > + sc->sc_dev.dv_xname, idx); > + return 1; > + } > + > + dsm_func = acpihid_dsm_funcs[idx]; > + > + DPRINTF(("%s: executing _DSM %s\n", sc->sc_dev.dv_xname, dsm_func)); > + > + if (!(sc->sc_dsm_fn_mask & idx)) { > + DPRINTF(("%s: _DSM mask does not support %s (%d), executing " > + "directly\n", sc->sc_dev.dv_xname, dsm_func, idx)); > + goto eval_direct; > + } > + > + bzero(&pkg, sizeof(pkg)); > + pkg.type = AML_OBJTYPE_INTEGER; > + pkg.v_integer = arg; > + pkg.length = 1; > + ppkg = &pkg; > + > + bzero(&cmd, sizeof(cmd)); > + cmd[0].type = AML_OBJTYPE_BUFFER; > + cmd[0].v_buffer = (uint8_t *)&acpihid_guid; > + cmd[0].length = sizeof(acpihid_guid); > + /* rev */ > + cmd[1].type = AML_OBJTYPE_INTEGER; > + cmd[1].v_integer = 1; > + cmd[1].length = 1; > + /* func */ > + cmd[2].type = AML_OBJTYPE_INTEGER; > + cmd[2].v_integer = idx; > + cmd[2].length = 1; > + /* arg */ > + cmd[3].type = AML_OBJTYPE_PACKAGE; > + cmd[3].length = 1; > + cmd[3].v_package = &ppkg; > + > + if (aml_evalinteger(acpi_softc, sc->sc_devnode, "_DSM", 4, cmd, > + &tret)) { > + DPRINTF(("%s: _DSM %s failed\n", sc->sc_dev.dv_xname, > + dsm_func)); > + return 1; > + } > + > + DPRINTF(("%s: _DSM eval of %s succeeded\n", sc->sc_dev.dv_xname, > + dsm_func)); > + > + if (ret != NULL) > + *ret = tret; > + > + return 0; > + > +eval_direct: > + cmd[0].type = AML_OBJTYPE_INTEGER; > + cmd[0].v_integer = arg; > + cmd[0].length = 1; > + > + if (aml_evalinteger(acpi_softc, sc->sc_devnode, dsm_func, 1, cmd, > + &tret) != 0) { > + printf("%s: exec of %s failed\n", sc->sc_dev.dv_xname, > + dsm_func); > + return 1; > + } > + > + if (ret != NULL) > + *ret = tret; > + > + return 0; > +} > + > +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_eval(sc, ACPIHID_FUNC_BTNE, enable ? cap : 1, NULL) != 0) { > + printf("%s: failed enabling button array\n", > + sc->sc_dev.dv_xname); > + 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 > + > + 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 */ > + break; > + default: > + printf("%s: unhandled button 0x%x\n", sc->sc_dev.dv_xname, > + notify_type); > + } > + > + return 0; > +} > diff --git sys/dev/acpi/files.acpi sys/dev/acpi/files.acpi > index 496d7ef1ed1..2c363be78cf 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 > + > +# Intel HID event and 5-button array > +device acpihid > +attach acpihid at acpi > +file dev/acpi/acpihid.c acpihid > >
