/* * If no AC line devices detected after boot, create an "online" event * so that userland code can adjust power settings accordingly. The default * power profile is "performance" so we don't need to repeat that here. */ static void acpi_acad_ac_only(void __unused *arg) { if (devclass_get_count(acpi_acad_devclass) == 0) acpi_UserNotify("ACAD", ACPI_ROOT_OBJECT, 1); }
static void acpi_acad_get_status(void *context) { struct acpi_acad_softc *sc; device_t dev; ACPI_HANDLE h; int newstatus; dev = context; sc = device_get_softc(dev); h = acpi_get_handle(dev); newstatus = -1; acpi_GetInteger(h, "_PSR", &newstatus); /* If status is valid and has changed, notify the system. */ ACPI_SERIAL_BEGIN(acad); if (newstatus != -1 && sc->status != newstatus) { sc->status = newstatus; power_profile_set_state(newstatus ? POWER_PROFILE_PERFORMANCE : POWER_PROFILE_ECONOMY); ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), "%s Line\n", newstatus ? "On" : "Off"); acpi_UserNotify("ACAD", h, newstatus); } ACPI_SERIAL_END(acad); }
static void acpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) { struct acpi_cmbat_softc *sc; device_t dev; dev = (device_t)context; sc = device_get_softc(dev); switch (notify) { case ACPI_NOTIFY_DEVICE_CHECK: case ACPI_BATTERY_BST_CHANGE: /* * Clear the last updated time. The next call to retrieve the * battery status will get the new value for us. */ timespecclear(&sc->bst_lastupdated); break; case ACPI_NOTIFY_BUS_CHECK: case ACPI_BATTERY_BIF_CHANGE: /* * Queue a callback to get the current battery info from thread * context. It's not safe to block in a notify handler. */ AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_get_bif_task, dev); break; } acpi_UserNotify("CMBAT", h, notify); }
static void acpi_tz_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) { struct acpi_tz_softc *sc = (struct acpi_tz_softc *)context; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); switch (notify) { case TZ_NOTIFY_TEMPERATURE: /* Temperature change occurred */ acpi_tz_signal(sc, 0); break; case TZ_NOTIFY_DEVICES: case TZ_NOTIFY_LEVELS: /* Zone devices/setpoints changed */ acpi_tz_signal(sc, TZ_FLAG_GETSETTINGS); break; default: ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev), "unknown Notify event 0x%x\n", notify); break; } acpi_UserNotify("Thermal", h, notify); return_VOID; }
static void acpi_button_notify_wakeup(void *arg) { struct acpi_button_softc *sc; struct acpi_softc *acpi_sc; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); sc = (struct acpi_button_softc *)arg; acpi_sc = acpi_device_get_parent_softc(sc->button_dev); 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"); acpi_event_power_button_wake(acpi_sc); break; case ACPI_SLEEP_BUTTON: ACPI_VPRINT(sc->button_dev, acpi_sc, "wakeup by sleep button\n"); acpi_event_sleep_button_wake(acpi_sc); break; default: break; /* unknown button type */ } }
static void acpi_panasonic_notify(ACPI_HANDLE h, UINT32 notify, void *context) { struct acpi_panasonic_softc *sc; UINT32 key = 0; sc = (struct acpi_panasonic_softc *)context; switch (notify) { case 0x80: ACPI_SERIAL_BEGIN(panasonic); if (acpi_panasonic_hkey_event(sc, h, &key) == 0) { acpi_panasonic_hkey_action(sc, h, key); acpi_UserNotify("Panasonic", h, (uint8_t)key); } ACPI_SERIAL_END(panasonic); break; default: device_printf(sc->dev, "unknown notify: %#x\n", notify); break; } }
static void acpi_lid_notify_status_changed(void *arg) { struct acpi_lid_softc *sc; struct acpi_softc *acpi_sc; ACPI_STATUS status; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); sc = (struct acpi_lid_softc *)arg; ACPI_SERIAL_BEGIN(lid); /* * Evaluate _LID and check the return value, update lid status. * Zero: The lid is closed * Non-zero: The lid is open */ status = acpi_GetInteger(sc->lid_handle, "_LID", &sc->lid_status); if (ACPI_FAILURE(status)) goto out; acpi_sc = acpi_device_get_parent_softc(sc->lid_dev); if (acpi_sc == NULL) goto out; 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 EVENTHANDLER_INVOKE(acpi_wakeup_event, acpi_sc->acpi_lid_switch_sx); out: ACPI_SERIAL_END(lid); return_VOID; }
/* * Query each of the ACPI control methods that contain information we're * interested in. We check the return values from the control methods and * adjust any state variables if they should be adjusted. */ static uint8_t acpi_fujitsu_update(struct acpi_fujitsu_softc *sc) { int changed; struct acpi_softc *acpi_sc; acpi_sc = acpi_device_get_parent_softc(sc->dev); ACPI_SERIAL_ASSERT(fujitsu); if(sc->gsif.exists) changed = sc->gsif.value & acpi_fujitsu_method_get(sc,METHOD_GHKS); else changed = 0; /* System Volume Level */ if(sc->gvol.exists) { if (ACPI_FAILURE(acpi_GetInteger(sc->handle, sc->gvol.name, &(sc->gvol.value)))) { device_printf(sc->dev, "Couldn't query volume level\n"); return (FALSE); } if (changed & VOLUME_CHANGED) { sc->bIsMuted = (uint8_t)((sc->gvol.value & VOLUME_MUTE_BIT) != 0); /* Clear the modification bit */ sc->gvol.value &= VOLUME_SETTING_BITS; if (sc->bIsMuted) { acpi_UserNotify("FUJITSU", sc->handle, FN_MUTE); ACPI_VPRINT(sc->dev, acpi_sc, "Volume is now mute\n"); } else ACPI_VPRINT(sc->dev, acpi_sc, "Volume is now %d\n", sc->gvol.value); acpi_UserNotify("FUJITSU", sc->handle, FN_VOLUME); } } /* Internal mouse pointer (eraserhead) */ if(sc->gmou.exists) { if (ACPI_FAILURE(acpi_GetInteger(sc->handle, sc->gmou.name, &(sc->gmou.value)))) { device_printf(sc->dev, "Couldn't query pointer state\n"); return (FALSE); } if (changed & MOUSE_CHANGED) { sc->bIntPtrEnabled = (uint8_t)(sc->gmou.value & 0x1); /* Clear the modification bit */ sc->gmou.value &= MOUSE_SETTING_BITS; /* Set the value in case it is not hardware controlled */ acpi_fujitsu_method_set(sc, METHOD_GMOU, sc->gmou.value); acpi_UserNotify("FUJITSU", sc->handle, FN_POINTER_ENABLE); ACPI_VPRINT(sc->dev, acpi_sc, "Internal pointer is now %s\n", (sc->bIntPtrEnabled) ? "enabled" : "disabled"); } } /* Screen Brightness Level P8XXX */ if(sc->gbls.exists) { if (ACPI_FAILURE(acpi_GetInteger(sc->handle, sc->gbls.name, &(sc->gbls.value)))) { device_printf(sc->dev, "Couldn't query P8XXX brightness level\n"); return (FALSE); } if (changed & BRIGHT_CHANGED) { /* No state to record here. */ /* Clear the modification bit */ sc->gbls.value &= BRIGHTNESS_SETTING_BITS; /* Set the value in case it is not hardware controlled */ acpi_fujitsu_method_set(sc, METHOD_GBLS, sc->gbls.value); acpi_UserNotify("FUJITSU", sc->handle, FN_LCD_BRIGHTNESS); ACPI_VPRINT(sc->dev, acpi_sc, "P8XXX Brightness level is now %d\n", sc->gbls.value); } } /* Screen Brightness Level */ if(sc->gbll.exists) { if (ACPI_FAILURE(acpi_GetInteger(sc->handle, sc->gbll.name, &(sc->gbll.value)))) { device_printf(sc->dev, "Couldn't query brightness level\n"); return (FALSE); } if (changed & BRIGHT_CHANGED) { /* No state to record here. */ /* Clear the modification bit */ sc->gbll.value &= BRIGHTNESS_SETTING_BITS; acpi_UserNotify("FUJITSU", sc->handle, FN_LCD_BRIGHTNESS); ACPI_VPRINT(sc->dev, acpi_sc, "Brightness level is now %d\n", sc->gbll.value); } } sc->lastValChanged = changed; return (TRUE); }
/* * Evaluate the condition of a thermal zone, take appropriate actions. */ static void acpi_tz_monitor(void *Context) { struct acpi_tz_softc *sc; struct timespec curtime; int temp; int i; int newactive, newflags; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); sc = (struct acpi_tz_softc *)Context; /* Get the current temperature. */ if (!acpi_tz_get_temperature(sc)) { /* XXX disable zone? go to max cooling? */ return_VOID; } temp = sc->tz_temperature; /* * Work out what we ought to be doing right now. * * Note that the _ACx levels sort from hot to cold. */ newactive = TZ_ACTIVE_NONE; for (i = TZ_NUMLEVELS - 1; i >= 0; i--) { if (sc->tz_zone.ac[i] != -1 && temp >= sc->tz_zone.ac[i]) newactive = i; } /* * We are going to get _ACx level down (colder side), but give a guaranteed * minimum cooling run time if requested. */ if (acpi_tz_min_runtime > 0 && sc->tz_active != TZ_ACTIVE_NONE && sc->tz_active != TZ_ACTIVE_UNKNOWN && (newactive == TZ_ACTIVE_NONE || newactive > sc->tz_active)) { getnanotime(&curtime); timespecsub(&curtime, &sc->tz_cooling_started); if (curtime.tv_sec < acpi_tz_min_runtime) newactive = sc->tz_active; } /* Handle user override of active mode */ if (sc->tz_requested != TZ_ACTIVE_NONE && (newactive == TZ_ACTIVE_NONE || sc->tz_requested < newactive)) newactive = sc->tz_requested; /* update temperature-related flags */ newflags = TZ_THFLAG_NONE; if (sc->tz_zone.psv != -1 && temp >= sc->tz_zone.psv) newflags |= TZ_THFLAG_PSV; if (sc->tz_zone.hot != -1 && temp >= sc->tz_zone.hot) newflags |= TZ_THFLAG_HOT; if (sc->tz_zone.crt != -1 && temp >= sc->tz_zone.crt) newflags |= TZ_THFLAG_CRT; /* If the active cooling state has changed, we have to switch things. */ if (sc->tz_active == TZ_ACTIVE_UNKNOWN) { /* * We don't know which cooling device is on or off, * so stop them all, because we now know which * should be on (if any). */ for (i = 0; i < TZ_NUMLEVELS; i++) { if (sc->tz_zone.al[i].Pointer != NULL) { acpi_ForeachPackageObject( (ACPI_OBJECT *)sc->tz_zone.al[i].Pointer, acpi_tz_switch_cooler_off, sc); } } /* now we know that all devices are off */ sc->tz_active = TZ_ACTIVE_NONE; } if (newactive != sc->tz_active) { /* Turn off unneeded cooling devices that are on, if any are */ for (i = TZ_ACTIVE_LEVEL(sc->tz_active); i < TZ_ACTIVE_LEVEL(newactive); i++) { acpi_ForeachPackageObject( (ACPI_OBJECT *)sc->tz_zone.al[i].Pointer, acpi_tz_switch_cooler_off, sc); } /* Turn on cooling devices that are required, if any are */ for (i = TZ_ACTIVE_LEVEL(sc->tz_active) - 1; i >= TZ_ACTIVE_LEVEL(newactive); i--) { acpi_ForeachPackageObject( (ACPI_OBJECT *)sc->tz_zone.al[i].Pointer, acpi_tz_switch_cooler_on, sc); } ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev), "switched from %s to %s: %d.%dC\n", acpi_tz_aclevel_string(sc->tz_active), acpi_tz_aclevel_string(newactive), TZ_KELVTOC(temp)); sc->tz_active = newactive; getnanotime(&sc->tz_cooling_started); } /* XXX (de)activate any passive cooling that may be required. */ /* * If the temperature is at _HOT or _CRT, increment our event count. * If it has occurred enough times, shutdown the system. This is * needed because some systems will report an invalid high temperature * for one poll cycle. It is suspected this is due to the embedded * controller timing out. A typical value is 138C for one cycle on * a system that is otherwise 65C. * * If we're almost at that threshold, notify the user through devd(8). */ if ((newflags & (TZ_THFLAG_HOT | TZ_THFLAG_CRT)) != 0) { sc->tz_validchecks++; if (sc->tz_validchecks == TZ_VALIDCHECKS) { device_printf(sc->tz_dev, "WARNING - current temperature (%d.%dC) exceeds safe limits\n", TZ_KELVTOC(sc->tz_temperature)); shutdown_nice(RB_POWEROFF); } else if (sc->tz_validchecks == TZ_NOTIFYCOUNT) acpi_UserNotify("Thermal", sc->tz_handle, TZ_NOTIFY_CRITICAL); } else { sc->tz_validchecks = 0; } sc->tz_thflags = newflags; return_VOID; }