acpi_button.c revision 1.25
11.25Sjmcneill/* $NetBSD: acpi_button.c,v 1.25 2007/12/09 20:27:52 jmcneill Exp $ */ 21.1Sthorpej 31.1Sthorpej/* 41.7Sthorpej * Copyright 2001, 2003 Wasabi Systems, Inc. 51.1Sthorpej * All rights reserved. 61.1Sthorpej * 71.1Sthorpej * Written by Jason R. Thorpe for Wasabi Systems, Inc. 81.1Sthorpej * 91.1Sthorpej * Redistribution and use in source and binary forms, with or without 101.1Sthorpej * modification, are permitted provided that the following conditions 111.1Sthorpej * are met: 121.1Sthorpej * 1. Redistributions of source code must retain the above copyright 131.1Sthorpej * notice, this list of conditions and the following disclaimer. 141.1Sthorpej * 2. Redistributions in binary form must reproduce the above copyright 151.1Sthorpej * notice, this list of conditions and the following disclaimer in the 161.1Sthorpej * documentation and/or other materials provided with the distribution. 171.1Sthorpej * 3. All advertising materials mentioning features or use of this software 181.1Sthorpej * must display the following acknowledgement: 191.1Sthorpej * This product includes software developed for the NetBSD Project by 201.1Sthorpej * Wasabi Systems, Inc. 211.1Sthorpej * 4. The name of Wasabi Systems, Inc. may not be used to endorse 221.1Sthorpej * or promote products derived from this software without specific prior 231.1Sthorpej * written permission. 241.1Sthorpej * 251.1Sthorpej * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 261.1Sthorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 271.1Sthorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 281.1Sthorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 291.1Sthorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 301.1Sthorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 311.1Sthorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 321.1Sthorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 331.1Sthorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 341.1Sthorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 351.1Sthorpej * POSSIBILITY OF SUCH DAMAGE. 361.1Sthorpej */ 371.1Sthorpej 381.1Sthorpej/* 391.1Sthorpej * ACPI Button driver. 401.1Sthorpej */ 411.2Slukem 421.2Slukem#include <sys/cdefs.h> 431.25Sjmcneill__KERNEL_RCSID(0, "$NetBSD: acpi_button.c,v 1.25 2007/12/09 20:27:52 jmcneill Exp $"); 441.1Sthorpej 451.1Sthorpej#include <sys/param.h> 461.1Sthorpej#include <sys/systm.h> 471.1Sthorpej#include <sys/device.h> 481.1Sthorpej 491.1Sthorpej#include <dev/acpi/acpica.h> 501.1Sthorpej#include <dev/acpi/acpireg.h> 511.1Sthorpej#include <dev/acpi/acpivar.h> 521.1Sthorpej 531.7Sthorpej#include <dev/sysmon/sysmonvar.h> 541.7Sthorpej 551.1Sthorpejstruct acpibut_softc { 561.1Sthorpej struct acpi_devnode *sc_node; /* our ACPI devnode */ 571.7Sthorpej struct sysmon_pswitch sc_smpsw; /* our sysmon glue */ 581.1Sthorpej int sc_flags; /* see below */ 591.1Sthorpej}; 601.1Sthorpej 611.15Skochistatic const char * const power_button_hid[] = { 621.11Skochi "PNP0C0C", 631.15Skochi NULL 641.15Skochi}; 651.15Skochi 661.15Skochistatic const char * const sleep_button_hid[] = { 671.11Skochi "PNP0C0E", 681.11Skochi NULL 691.11Skochi}; 701.11Skochi 711.1Sthorpej#define ACPIBUT_F_VERBOSE 0x01 /* verbose events */ 721.1Sthorpej 731.23Sjoergstatic int acpibut_match(device_t, struct cfdata *, void *); 741.23Sjoergstatic void acpibut_attach(device_t, device_t, void *); 751.1Sthorpej 761.23SjoergCFATTACH_DECL_NEW(acpibut, sizeof(struct acpibut_softc), 771.6Sthorpej acpibut_match, acpibut_attach, NULL, NULL); 781.1Sthorpej 791.16Skochistatic void acpibut_pressed_event(void *); 801.19Skochistatic void acpibut_notify_handler(ACPI_HANDLE, UINT32, void *); 811.1Sthorpej 821.1Sthorpej/* 831.1Sthorpej * acpibut_match: 841.1Sthorpej * 851.1Sthorpej * Autoconfiguration `match' routine. 861.1Sthorpej */ 871.16Skochistatic int 881.23Sjoergacpibut_match(device_t parent, struct cfdata *match, void *aux) 891.1Sthorpej{ 901.1Sthorpej struct acpi_attach_args *aa = aux; 911.1Sthorpej 921.1Sthorpej if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) 931.14Skochi return 0; 941.1Sthorpej 951.15Skochi if (acpi_match_hid(aa->aa_node->ad_devinfo, power_button_hid)) 961.15Skochi return 1; 971.15Skochi 981.15Skochi if (acpi_match_hid(aa->aa_node->ad_devinfo, sleep_button_hid)) 991.15Skochi return 1; 1001.15Skochi 1011.15Skochi return 0; 1021.1Sthorpej} 1031.1Sthorpej 1041.1Sthorpej/* 1051.1Sthorpej * acpibut_attach: 1061.1Sthorpej * 1071.1Sthorpej * Autoconfiguration `attach' routine. 1081.1Sthorpej */ 1091.16Skochistatic void 1101.23Sjoergacpibut_attach(device_t parent, device_t self, void *aux) 1111.1Sthorpej{ 1121.23Sjoerg struct acpibut_softc *sc = device_private(self); 1131.1Sthorpej struct acpi_attach_args *aa = aux; 1141.1Sthorpej const char *desc; 1151.1Sthorpej ACPI_STATUS rv; 1161.1Sthorpej 1171.23Sjoerg sc->sc_smpsw.smpsw_name = device_xname(self); 1181.7Sthorpej 1191.15Skochi if (acpi_match_hid(aa->aa_node->ad_devinfo, power_button_hid)) { 1201.9Sthorpej sc->sc_smpsw.smpsw_type = PSWITCH_TYPE_POWER; 1211.1Sthorpej desc = "Power"; 1221.15Skochi } else if (acpi_match_hid(aa->aa_node->ad_devinfo, sleep_button_hid)) { 1231.9Sthorpej sc->sc_smpsw.smpsw_type = PSWITCH_TYPE_SLEEP; 1241.1Sthorpej desc = "Sleep"; 1251.1Sthorpej } else { 1261.1Sthorpej panic("acpibut_attach: impossible"); 1271.1Sthorpej } 1281.1Sthorpej 1291.20Skochi aprint_naive(": ACPI %s Button\n", desc); 1301.20Skochi aprint_normal(": ACPI %s Button\n", desc); 1311.1Sthorpej 1321.1Sthorpej sc->sc_node = aa->aa_node; 1331.1Sthorpej 1341.7Sthorpej if (sysmon_pswitch_register(&sc->sc_smpsw) != 0) { 1351.23Sjoerg aprint_error_dev(self, "unable to register with sysmon\n"); 1361.7Sthorpej return; 1371.7Sthorpej } 1381.7Sthorpej 1391.1Sthorpej rv = AcpiInstallNotifyHandler(sc->sc_node->ad_handle, 1401.23Sjoerg ACPI_DEVICE_NOTIFY, acpibut_notify_handler, self); 1411.13Smycroft if (ACPI_FAILURE(rv)) { 1421.23Sjoerg aprint_error_dev(self, 1431.23Sjoerg "unable to register DEVICE NOTIFY handler: %s\n", 1441.23Sjoerg AcpiFormatException(rv)); 1451.1Sthorpej return; 1461.1Sthorpej } 1471.1Sthorpej 1481.17Skochi acpi_set_wake_gpe(sc->sc_node->ad_handle); 1491.17Skochi 1501.1Sthorpej#ifdef ACPI_BUT_DEBUG 1511.1Sthorpej /* Display the current state when it changes. */ 1521.1Sthorpej sc->sc_flags = ACPIBUT_F_VERBOSE; 1531.1Sthorpej#endif 1541.25Sjmcneill 1551.25Sjmcneill if (!pmf_device_register(self, NULL, NULL)) 1561.25Sjmcneill aprint_error_dev(self, "couldn't establish power handler\n"); 1571.1Sthorpej} 1581.1Sthorpej 1591.1Sthorpej/* 1601.7Sthorpej * acpibut_pressed_event: 1611.1Sthorpej * 1621.7Sthorpej * Deal with a button being pressed. 1631.1Sthorpej */ 1641.16Skochistatic void 1651.7Sthorpejacpibut_pressed_event(void *arg) 1661.1Sthorpej{ 1671.23Sjoerg device_t dv = arg; 1681.23Sjoerg struct acpibut_softc *sc = device_private(dv); 1691.1Sthorpej 1701.1Sthorpej if (sc->sc_flags & ACPIBUT_F_VERBOSE) 1711.23Sjoerg aprint_verbose_dev(dv, "button pressed\n"); 1721.1Sthorpej 1731.9Sthorpej sysmon_pswitch_event(&sc->sc_smpsw, PSWITCH_EVENT_PRESSED); 1741.1Sthorpej} 1751.1Sthorpej 1761.1Sthorpej/* 1771.1Sthorpej * acpibut_notify_handler: 1781.1Sthorpej * 1791.1Sthorpej * Callback from ACPI interrupt handler to notify us of an event. 1801.1Sthorpej */ 1811.16Skochistatic void 1821.23Sjoergacpibut_notify_handler(ACPI_HANDLE handle, UINT32 notify, void *context) 1831.1Sthorpej{ 1841.23Sjoerg device_t dv = context; 1851.1Sthorpej int rv; 1861.1Sthorpej 1871.1Sthorpej switch (notify) { 1881.1Sthorpej case ACPI_NOTIFY_S0PowerButtonPressed: 1891.1Sthorpej#if 0 1901.1Sthorpej case ACPI_NOTIFY_S0SleepButtonPressed: /* same as above */ 1911.1Sthorpej#endif 1921.1Sthorpej#ifdef ACPI_BUT_DEBUG 1931.23Sjoerg aprint_debug_dev(dv, "received ButtonPressed message\n"); 1941.1Sthorpej#endif 1951.25Sjmcneill rv = AcpiOsExecute(OSL_NOTIFY_HANDLER, 1961.24Sjoerg acpibut_pressed_event, dv); 1971.13Smycroft if (ACPI_FAILURE(rv)) 1981.23Sjoerg aprint_error_dev(dv, 1991.23Sjoerg "WARNING: unable to queue button pressed callback: %s\n", 2001.12Smycroft AcpiFormatException(rv)); 2011.1Sthorpej break; 2021.1Sthorpej 2031.1Sthorpej /* XXX ACPI_NOTIFY_DeviceWake?? */ 2041.1Sthorpej 2051.1Sthorpej default: 2061.23Sjoerg aprint_error_dev(dv, "received unknown notify message: 0x%x\n", 2071.23Sjoerg notify); 2081.1Sthorpej } 2091.1Sthorpej} 210