From 9b937d4836af13ea4e86868b9bd4e1cc09dee732 Mon Sep 17 00:00:00 2001 From: Nate Lawson Date: Sat, 25 Oct 2003 05:03:25 +0000 Subject: [PATCH] Add devctl(4) notify support to ACPI. Various subsystems now notify userland whenever events occur. See the example in devd.conf below to see how to use it. --- etc/devd.conf | 26 ++++++++++++++++++++++++++ sys/dev/acpica/acpi.c | 22 ++++++++++++++++++++++ sys/dev/acpica/acpi_acad.c | 4 +++- sys/dev/acpica/acpi_button.c | 4 ++++ sys/dev/acpica/acpi_cmbat.c | 2 ++ sys/dev/acpica/acpi_lid.c | 6 ++++-- sys/dev/acpica/acpi_thermal.c | 2 ++ sys/dev/acpica/acpivar.h | 2 ++ 8 files changed, 65 insertions(+), 3 deletions(-) diff --git a/etc/devd.conf b/etc/devd.conf index 299911520bdf..4f4641578aa1 100644 --- a/etc/devd.conf +++ b/etc/devd.conf @@ -93,4 +93,30 @@ detach 10 { action "/etc/pccard_ether $device-name stop"; }; +# Examples of notify hooks. A notify is a generic way for a kernel +# subsystem to send event notification to userland. +# +# Here are some examples of ACPI notify handlers. ACPI subsystems that +# generate notifies include the AC adapter, power/sleep buttons, +# control method batteries, lid switch, and thermal zones. +# +# Information returned is not always the same as the ACPI notify +# events. See the ACPI specification for more information about +# notifies. Here is the information returned for each subsystem: +# +# ACAD: AC line state (0 is offline, 1 is online) +# Button: Button pressed (0 for power, 1 for sleep) +# CMBAT: ACPI battery events +# Lid: Lid state (0 is closed, 1 is open) +# Thermal: ACPI thermal zone events +# +# This example calls a script when the AC state changes, passing the +# notify value as the first argument. If the state is 0x00, it might +# call some sysctls to implement economy mode. If 0x01, it might set +# the mode to performance. +notify 10 { + match "system" "ACPI"; + match "subsystem" "ACAD"; + action "/etc/acpi_ac $notify"; +}; */ diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index 43dca2ab37c6..33cb20c0501c 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -51,6 +51,7 @@ #include "acpi.h" #include #include +#include MALLOC_DEFINE(M_ACPIDEV, "acpidev", "ACPI devices"); @@ -2054,6 +2055,27 @@ acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS) return (error); } +/* Inform devctl(4) when we receive a Notify. */ +void +acpi_UserNotify(const char *subsystem, ACPI_HANDLE h, uint8_t notify) +{ + char notify_buf[16]; + ACPI_BUFFER handle_buf; + ACPI_STATUS status; + + if (subsystem == NULL) + return; + + handle_buf.Pointer = NULL; + handle_buf.Length = ACPI_ALLOCATE_BUFFER; + status = AcpiNsHandleToPathname(h, &handle_buf); + if (ACPI_FAILURE(status)) + return; + snprintf(notify_buf, sizeof(notify_buf), "notify=0x%02x", notify); + devctl_notify("ACPI", subsystem, handle_buf.Pointer, notify_buf); + AcpiOsFree(handle_buf.Pointer); +} + #ifdef ACPI_DEBUG /* * Support for parsing debug options from the kernel environment. diff --git a/sys/dev/acpica/acpi_acad.c b/sys/dev/acpica/acpi_acad.c index 601f96cfe720..29b8bb9385b5 100644 --- a/sys/dev/acpica/acpi_acad.c +++ b/sys/dev/acpica/acpi_acad.c @@ -39,7 +39,7 @@ #include #include -#include "acpi.h" +#include "acpi.h" #include #include @@ -108,6 +108,8 @@ acpi_acad_get_status(void *context) POWER_PROFILE_ECONOMY); ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), "%s Line\n", sc->status ? "On" : "Off"); + + acpi_UserNotify("ACAD", h, sc->status); } } diff --git a/sys/dev/acpica/acpi_button.c b/sys/dev/acpica/acpi_button.c index ab8ba217796f..33ace7870f38 100644 --- a/sys/dev/acpica/acpi_button.c +++ b/sys/dev/acpica/acpi_button.c @@ -175,6 +175,8 @@ acpi_button_notify_pressed_for_sleep(void *arg) if (acpi_sc == NULL) return_VOID; + acpi_UserNotify("Button", sc->button_handle, sc->button_type); + switch (sc->button_type) { case ACPI_POWER_BUTTON: ACPI_VPRINT(sc->button_dev, acpi_sc, "power button pressed\n"); @@ -202,6 +204,8 @@ acpi_button_notify_pressed_for_wakeup(void *arg) if (acpi_sc == NULL) return_VOID; + acpi_UserNotify("Button", sc->button_handle, sc->button_type); + switch (sc->button_type) { case ACPI_POWER_BUTTON: ACPI_VPRINT(sc->button_dev, acpi_sc, "wakeup by power button\n"); diff --git a/sys/dev/acpica/acpi_cmbat.c b/sys/dev/acpica/acpi_cmbat.c index b5bebc9db084..d14ea7148bf8 100644 --- a/sys/dev/acpica/acpi_cmbat.c +++ b/sys/dev/acpica/acpi_cmbat.c @@ -295,6 +295,8 @@ acpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) if ((sc = device_get_softc(dev)) == NULL) return; + acpi_UserNotify("CMBAT", h, notify); + switch (notify) { case ACPI_NOTIFY_DEVICE_CHECK: case ACPI_BATTERY_BST_CHANGE: diff --git a/sys/dev/acpica/acpi_lid.c b/sys/dev/acpica/acpi_lid.c index d855a47716f9..ecb8ccc526c9 100644 --- a/sys/dev/acpica/acpi_lid.c +++ b/sys/dev/acpica/acpi_lid.c @@ -54,7 +54,8 @@ static int acpi_lid_attach(device_t dev); static int acpi_lid_suspend(device_t dev); static int acpi_lid_resume(device_t dev); static void acpi_lid_notify_status_changed(void *arg); -static void acpi_lid_notify_handler(ACPI_HANDLE h,UINT32 notify, void *context); +static void acpi_lid_notify_handler(ACPI_HANDLE h, UINT32 notify, + void *context); static device_method_t acpi_lid_methods[] = { /* Device interface */ @@ -149,6 +150,8 @@ acpi_lid_notify_status_changed(void *arg) ACPI_VPRINT(sc->lid_dev, acpi_sc, "Lid %s\n", sc->lid_status ? "opened" : "closed"); + acpi_UserNotify("Lid", sc->lid_handle, sc->lid_status); + if (sc->lid_status == 0) EVENTHANDLER_INVOKE(acpi_sleep_event, acpi_sc->acpi_lid_switch_sx); else @@ -178,4 +181,3 @@ acpi_lid_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) return_VOID; } - diff --git a/sys/dev/acpica/acpi_thermal.c b/sys/dev/acpica/acpi_thermal.c index 86ee65671a26..df704ec827f3 100644 --- a/sys/dev/acpica/acpi_thermal.c +++ b/sys/dev/acpica/acpi_thermal.c @@ -727,6 +727,8 @@ acpi_tz_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) break; } + acpi_UserNotify("Thermal", h, notify); + return_VOID; } diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h index 578a6c0f999e..77e36ad38f8f 100644 --- a/sys/dev/acpica/acpivar.h +++ b/sys/dev/acpica/acpivar.h @@ -188,6 +188,8 @@ extern ACPI_STATUS acpi_SetIntrModel(int model); extern ACPI_STATUS acpi_SetSleepState(struct acpi_softc *sc, int state); extern ACPI_STATUS acpi_Enable(struct acpi_softc *sc); extern ACPI_STATUS acpi_Disable(struct acpi_softc *sc); +extern void acpi_UserNotify(const char *subsystem, ACPI_HANDLE h, + uint8_t notify); struct acpi_parse_resource_set { void (*set_init)(device_t dev, void **context);