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

Reply via email to