summaryrefslogtreecommitdiff
path: root/sys/dev/acpi/acpithinkpad.c
diff options
context:
space:
mode:
authorjoshua stein <jcs@cvs.openbsd.org>2008-05-14 02:02:06 +0000
committerjoshua stein <jcs@cvs.openbsd.org>2008-05-14 02:02:06 +0000
commit0677585573a0200ea4a3039561de3b057dd2d526 (patch)
tree6590a40c69c877589f00dc9c137f633be6b50be0 /sys/dev/acpi/acpithinkpad.c
parent6e1e877d6f62924be199fa22500c3638e84b5ada (diff)
recognize some more events
hook up the volume keys to actually do stuff; from Stefan Kempf use aml_freevalue to properly free memory in all cases; prodded by deanna
Diffstat (limited to 'sys/dev/acpi/acpithinkpad.c')
-rw-r--r--sys/dev/acpi/acpithinkpad.c90
1 files changed, 82 insertions, 8 deletions
diff --git a/sys/dev/acpi/acpithinkpad.c b/sys/dev/acpi/acpithinkpad.c
index 47066f53579..a434bcff06b 100644
--- a/sys/dev/acpi/acpithinkpad.c
+++ b/sys/dev/acpi/acpithinkpad.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpithinkpad.c,v 1.1 2008/04/27 16:23:16 jcs Exp $ */
+/* $OpenBSD: acpithinkpad.c,v 1.2 2008/05/14 02:02:05 jcs Exp $ */
/*
* Copyright (c) 2008 joshua stein <jcs@openbsd.org>
@@ -27,6 +27,9 @@
#define THINKPAD_HKEY_VERSION 0x0100
+#define THINKPAD_CMOS_VOLUME_DOWN 0x00
+#define THINKPAD_CMOS_VOLUME_UP 0x01
+#define THINKPAD_CMOS_VOLUME_MUTE 0x02
#define THINKPAD_CMOS_BRIGHTNESS_UP 0x04
#define THINKPAD_CMOS_BRIGHTNESS_DOWN 0x05
@@ -51,6 +54,9 @@
#define THINKPAD_BUTTON_BRIGHTNESS_DOWN 0x011
#define THINKPAD_BUTTON_THINKLIGHT 0x012
#define THINKPAD_BUTTON_FN_SPACE 0x014
+#define THINKPAD_BUTTON_VOLUME_UP 0x015
+#define THINKPAD_BUTTON_VOLUME_DOWN 0x016
+#define THINKPAD_BUTTON_VOLUME_MUTE 0x017
#define THINKPAD_BUTTON_THINKVANTAGE 0x018
#define THINKPAD_BUTTON_FN_F11 0x00b
#define THINKPAD_BUTTON_HIBERNATE 0x00c
@@ -63,6 +69,9 @@
#define THINKPAD_TABLET_PEN_INSERTED 0x00b
#define THINKPAD_TABLET_PEN_REMOVED 0x00c
+/* type 7 events */
+#define THINKPAD_SWITCH_WIRELESS 0x000
+
struct acpithinkpad_softc {
struct device sc_dev;
@@ -77,6 +86,9 @@ int thinkpad_enable_events(struct acpithinkpad_softc *);
int thinkpad_toggle_bluetooth(struct acpithinkpad_softc *);
int thinkpad_toggle_wan(struct acpithinkpad_softc *);
int thinkpad_cmos(struct acpithinkpad_softc *sc, uint8_t);
+int thinkpad_volume_down(struct acpithinkpad_softc *);
+int thinkpad_volume_up(struct acpithinkpad_softc *);
+int thinkpad_volume_mute(struct acpithinkpad_softc *);
int thinkpad_brightness_up(struct acpithinkpad_softc *);
int thinkpad_brightness_down(struct acpithinkpad_softc *);
@@ -107,6 +119,7 @@ thinkpad_match(struct device *parent, void *match, void *aux)
if (aml_val2int(&res) != THINKPAD_HKEY_VERSION)
goto fail;
+ aml_freevalue(&res);
return (1);
fail:
@@ -118,7 +131,7 @@ void
thinkpad_attach(struct device *parent, struct device *self, void *aux)
{
struct acpithinkpad_softc *sc = (struct acpithinkpad_softc *)self;
- struct acpi_attach_args *aa = aux;
+ struct acpi_attach_args *aa = aux;
sc->sc_acpi = (struct acpi_softc *)parent;
sc->sc_devnode = aa->aaa_node->child;
@@ -145,8 +158,7 @@ thinkpad_enable_events(struct acpithinkpad_softc *sc)
/* get the supported event mask */
if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "MHKA", 0, NULL, &res)) {
printf("%s: no MHKA\n", DEVNAME(sc));
- aml_freevalue(&res);
- return (1);
+ goto fail;
}
mask = aml_val2int(&res);
@@ -160,7 +172,7 @@ thinkpad_enable_events(struct acpithinkpad_softc *sc)
if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "MHKM", 2, args,
NULL)) {
printf("%s: couldn't toggle MHKM\n", DEVNAME(sc));
- return (1);
+ goto fail;
}
}
@@ -170,10 +182,24 @@ thinkpad_enable_events(struct acpithinkpad_softc *sc)
arg.v_integer = 1;
if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "MHKC", 1, &arg, NULL)) {
printf("%s: couldn't enable hotkeys\n", DEVNAME(sc));
- return (1);
+ goto fail;
}
+ aml_freevalue(&res);
+ aml_freevalue(&args[0]);
+ aml_freevalue(&args[1]);
+ aml_freevalue(&args[2]);
+ aml_freevalue(&arg);
+
return (0);
+
+fail:
+ aml_freevalue(&res);
+ aml_freevalue(&args[0]);
+ aml_freevalue(&args[1]);
+ aml_freevalue(&args[2]);
+ aml_freevalue(&arg);
+ return (1);
}
int
@@ -191,6 +217,7 @@ thinkpad_hotkey(struct aml_node *node, int notify_type, void *arg)
}
val = aml_val2int(&res);
+ aml_freevalue(&res);
if (val == 0)
return (1);
@@ -230,9 +257,22 @@ thinkpad_hotkey(struct aml_node *node, int notify_type, void *arg)
case THINKPAD_BUTTON_EJECT:
case THINKPAD_BUTTON_THINKLIGHT:
case THINKPAD_BUTTON_FN_SPACE:
+ handled = 1;
+ break;
+ case THINKPAD_BUTTON_VOLUME_DOWN:
+ thinkpad_volume_down(sc);
+ handled = 1;
+ break;
+ case THINKPAD_BUTTON_VOLUME_UP:
+ thinkpad_volume_up(sc);
+ handled = 1;
+ break;
+ case THINKPAD_BUTTON_VOLUME_MUTE:
+ thinkpad_volume_mute(sc);
+ handled = 1;
+ break;
case THINKPAD_BUTTON_THINKVANTAGE:
case THINKPAD_BUTTON_FN_F11:
- /* TODO: notify userland */
handled = 1;
break;
}
@@ -246,12 +286,19 @@ thinkpad_hotkey(struct aml_node *node, int notify_type, void *arg)
case THINKPAD_LID_CLOSED:
case THINKPAD_TABLET_PEN_INSERTED:
case THINKPAD_TABLET_PEN_REMOVED:
- /* TODO: notify userland */
handled = 1;
break;
}
break;
+ case 7:
+ switch (event) {
+ case THINKPAD_SWITCH_WIRELESS:
+ handled = 1;
+
+ break;
+ }
+ break;
}
if (!handled)
@@ -282,9 +329,12 @@ thinkpad_toggle_bluetooth(struct acpithinkpad_softc *sc)
arg.v_integer = bluetooth ^= THINKPAD_BLUETOOTH_ENABLED;
if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "SBDC", 1, &arg, NULL)) {
printf("%s: couldn't toggle bluetooth\n", DEVNAME(sc));
+ aml_freevalue(&arg);
return (1);
}
+ aml_freevalue(&arg);
+
return (0);
}
@@ -309,9 +359,12 @@ thinkpad_toggle_wan(struct acpithinkpad_softc *sc)
arg.v_integer = wan ^= THINKPAD_WAN_ENABLED;
if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "SWAN", 1, &arg, NULL)) {
printf("%s: couldn't toggle wan\n", DEVNAME(sc));
+ aml_freevalue(&arg);
return (1);
}
+ aml_freevalue(&arg);
+
return (0);
}
@@ -327,13 +380,34 @@ thinkpad_cmos(struct acpithinkpad_softc *sc, uint8_t cmd)
if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "\\UCMS", 1, &arg,
NULL)) {
printf("%s: cmos command 0x%x failed\n", DEVNAME(sc), cmd);
+ aml_freevalue(&arg);
return (1);
}
+ aml_freevalue(&arg);
+
return (0);
}
int
+thinkpad_volume_down(struct acpithinkpad_softc *sc)
+{
+ return thinkpad_cmos(sc, THINKPAD_CMOS_VOLUME_DOWN);
+}
+
+int
+thinkpad_volume_up(struct acpithinkpad_softc *sc)
+{
+ return thinkpad_cmos(sc, THINKPAD_CMOS_VOLUME_UP);
+}
+
+int
+thinkpad_volume_mute(struct acpithinkpad_softc *sc)
+{
+ return thinkpad_cmos(sc, THINKPAD_CMOS_VOLUME_MUTE);
+}
+
+int
thinkpad_brightness_up(struct acpithinkpad_softc *sc)
{
return thinkpad_cmos(sc, THINKPAD_CMOS_BRIGHTNESS_UP);