Permalink
Browse files

add acpihid driver for intel hid events and 5-button array

this makes the volume buttons on the surface type cover work
  • Loading branch information...
jcs committed Aug 28, 2018
1 parent f69ea46 commit 0befab1a6ae8708140d418d5affeb0a76d84ce4b
Showing with 243 additions and 2 deletions.
  1. +1 −0 sys/arch/amd64/conf/GENERIC
  2. +3 −1 sys/dev/acpi/acpi.c
  3. +1 −1 sys/dev/acpi/acpibtn.c
  4. +232 −0 sys/dev/acpi/acpihid.c
  5. +1 −0 sys/dev/acpi/acpivar.h
  6. +5 −0 sys/dev/acpi/files.acpi
@@ -68,6 +68,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?
@@ -71,6 +71,7 @@ int acpi_debug = 16;
int acpi_poll_enabled;
int acpi_hasprocfvs;
int acpi_hashidpower = 0;
#define ACPIEN_RETRIES 15
@@ -1967,7 +1968,8 @@ acpi_pbtn_task(void *arg0, int dummy)
en | ACPI_PM1_PWRBTN_EN);
splx(s);
acpi_addtask(sc, acpi_powerdown_task, sc, 0);
if (!acpi_hashidpower)
acpi_addtask(sc, acpi_powerdown_task, sc, 0);
}
void
@@ -269,7 +269,7 @@ acpibtn_notify(struct aml_node *node, int notify_type, void *arg)
#endif /* SMALL_KERNEL */
break;
case ACPIBTN_POWER:
if (notify_type == 0x80)
if (!acpi_hashidpower && notify_type == 0x80)
acpi_addtask(sc->sc_acpi, acpi_powerdown_task,
sc->sc_acpi, 0);
break;
@@ -0,0 +1,232 @@
/* $OpenBSD$ */
/*
* ACPI Intel HID event and 5-button array driver
* Copyright (c) 2018 joshua stein <jcs@openbsd.org>
*
* 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;
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)
{
#ifdef ACPIHID_DEBUG
struct acpihid_softc *sc = arg;
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 */
acpi_addtask(acpi_softc, acpi_powerdown_task, acpi_softc, 0);
break;
}
return 0;
}
@@ -43,6 +43,7 @@ extern int acpi_debug;
#endif
extern int acpi_hasprocfvs;
extern int acpi_hashidpower;
struct klist;
struct acpiec_softc;
@@ -193,3 +193,8 @@ file dev/acpi/acpisurface.c acpisurface
# IPMI
attach ipmi at acpi with ipmi_acpi
file dev/acpi/ipmi_acpi.c ipmi_acpi
# Intel HID event and 5-button array
device acpihid
attach acpihid at acpi
file dev/acpi/acpihid.c acpihid

0 comments on commit 0befab1

Please sign in to comment.