Module Name: src Committed By: jruoho Date: Thu Apr 8 09:35:15 UTC 2010
Added Files: src/sys/dev/acpi/wmi: files.wmi wmi_dell.c Log Message: Add WMI mappings for Dell laptops. Requested and tested by m...@. To generate a diff of this commit: cvs rdiff -u -r0 -r1.1 src/sys/dev/acpi/wmi/files.wmi \ src/sys/dev/acpi/wmi/wmi_dell.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Added files: Index: src/sys/dev/acpi/wmi/files.wmi diff -u /dev/null src/sys/dev/acpi/wmi/files.wmi:1.1 --- /dev/null Thu Apr 8 09:35:15 2010 +++ src/sys/dev/acpi/wmi/files.wmi Thu Apr 8 09:35:15 2010 @@ -0,0 +1,6 @@ +# $NetBSD: files.wmi,v 1.1 2010/04/08 09:35:15 jruoho Exp $ + +# Dell WMI mappings +device wmidell: sysmon_power +attach wmidell at acpiwmibus +file dev/acpi/wmi/wmi_dell.c wmidell Index: src/sys/dev/acpi/wmi/wmi_dell.c diff -u /dev/null src/sys/dev/acpi/wmi/wmi_dell.c:1.1 --- /dev/null Thu Apr 8 09:35:15 2010 +++ src/sys/dev/acpi/wmi/wmi_dell.c Thu Apr 8 09:35:15 2010 @@ -0,0 +1,231 @@ +/* $NetBSD: wmi_dell.c,v 1.1 2010/04/08 09:35:15 jruoho Exp $ */ + +/*- + * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jukka Ruohonen. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: wmi_dell.c,v 1.1 2010/04/08 09:35:15 jruoho Exp $"); + +#include <sys/param.h> +#include <sys/device.h> + +#include <dev/acpi/acpireg.h> +#include <dev/acpi/acpivar.h> +#include <dev/acpi/wmi_acpivar.h> + +#include <dev/sysmon/sysmonvar.h> + +#define _COMPONENT ACPI_RESOURCE_COMPONENT +ACPI_MODULE_NAME ("wmi_dell") + +#define WMI_DELL_HOTKEY_BRIGHTNESS_DOWN 0xE005 +#define WMI_DELL_HOTKEY_BRIGHTNESS_UP 0xE006 +#define WMI_DELL_HOTKEY_DISPLAY_CYCLE 0xE00B +#define WMI_DELL_HOTKEY_VOLUME_MUTE 0xE020 +#define WMI_DELL_HOTKEY_VOLUME_DOWN 0xE02E +#define WMI_DELL_HOTKEY_VOLUME_UP 0xE030 +/* WMI_DELL_HOTKEY_UNKNOWN 0xXXXX */ + +#define WMI_DELL_PSW_DISPLAY_CYCLE 0 +#define WMI_DELL_PSW_COUNT 1 + +#define WMI_DELL_GUID_EVENT "9DBB5994-A997-11DA-B012-B622A1EF5492" + +struct wmi_dell_softc { + device_t sc_dev; + device_t sc_parent; + struct sysmon_pswitch sc_smpsw[WMI_DELL_PSW_COUNT]; + bool sc_smpsw_valid; +}; + +static int wmi_dell_match(device_t, cfdata_t, void *); +static void wmi_dell_attach(device_t, device_t, void *); +static int wmi_dell_detach(device_t, int); +static void wmi_dell_notify_handler(ACPI_HANDLE, uint32_t, void *); +static bool wmi_dell_suspend(device_t, const pmf_qual_t *); +static bool wmi_dell_resume(device_t, const pmf_qual_t *); + +CFATTACH_DECL_NEW(wmidell, sizeof(struct wmi_dell_softc), + wmi_dell_match, wmi_dell_attach, wmi_dell_detach, NULL); + +static int +wmi_dell_match(device_t parent, cfdata_t match, void *aux) +{ + return acpi_wmi_guid_match(parent, WMI_DELL_GUID_EVENT); +} + +static void +wmi_dell_attach(device_t parent, device_t self, void *aux) +{ + struct wmi_dell_softc *sc = device_private(self); + ACPI_STATUS rv; + int e; + + sc->sc_dev = self; + sc->sc_parent = parent; + sc->sc_smpsw_valid = true; + + rv = acpi_wmi_event_register(parent, wmi_dell_notify_handler); + + if (ACPI_FAILURE(rv)) { + aprint_error(": failed to install WMI notify handler\n"); + return; + } + + aprint_naive("\n"); + aprint_normal(": Dell WMI mappings\n"); + + sc->sc_smpsw[WMI_DELL_PSW_DISPLAY_CYCLE].smpsw_name = + PSWITCH_HK_DISPLAY_CYCLE; + + sc->sc_smpsw[WMI_DELL_PSW_DISPLAY_CYCLE].smpsw_type = + PSWITCH_TYPE_HOTKEY; + + e = sysmon_pswitch_register(&sc->sc_smpsw[WMI_DELL_PSW_DISPLAY_CYCLE]); + + if (e != 0) + sc->sc_smpsw_valid = false; + + (void)pmf_device_register(self, wmi_dell_suspend, wmi_dell_resume); +} + +static int +wmi_dell_detach(device_t self, int flags) +{ + struct wmi_dell_softc *sc = device_private(self); + device_t parent = sc->sc_parent; + int i; + + (void)pmf_device_deregister(self); + (void)acpi_wmi_event_register(parent, NULL); + + if (sc->sc_smpsw_valid != true) + return 0; + + for (i = 0; i < __arraycount(sc->sc_smpsw); i++) + sysmon_pswitch_unregister(&sc->sc_smpsw[i]); + + return 0; +} + +static bool +wmi_dell_suspend(device_t self, const pmf_qual_t *qual) +{ + struct wmi_dell_softc *sc = device_private(self); + device_t parent = sc->sc_parent; + + (void)acpi_wmi_event_register(parent, NULL); + + return true; +} + +static bool +wmi_dell_resume(device_t self, const pmf_qual_t *qual) +{ + struct wmi_dell_softc *sc = device_private(self); + device_t parent = sc->sc_parent; + + (void)acpi_wmi_event_register(parent, wmi_dell_notify_handler); + + return true; +} + +static void +wmi_dell_notify_handler(ACPI_HANDLE hdl, uint32_t evt, void *aux) +{ + struct wmi_dell_softc *sc; + device_t self = aux; + ACPI_OBJECT *obj; + ACPI_BUFFER buf; + ACPI_STATUS rv; + uint32_t val; + + sc = device_private(self); + rv = acpi_wmi_event_get(sc->sc_parent, evt, &buf); + + if (ACPI_FAILURE(rv)) + goto out; + + obj = buf.Pointer; + + if (obj->Type != ACPI_TYPE_BUFFER) { + rv = AE_TYPE; + goto out; + } + + val = obj->Buffer.Pointer[1] & 0xFFFF; + + switch (val) { + + case WMI_DELL_HOTKEY_BRIGHTNESS_DOWN: + pmf_event_inject(NULL, PMFE_DISPLAY_BRIGHTNESS_DOWN); + break; + + case WMI_DELL_HOTKEY_BRIGHTNESS_UP: + pmf_event_inject(NULL, PMFE_DISPLAY_BRIGHTNESS_UP); + break; + + case WMI_DELL_HOTKEY_DISPLAY_CYCLE: + + if (sc->sc_smpsw_valid != true) { + rv = AE_ABORT_METHOD; + break; + } + + sysmon_pswitch_event(&sc->sc_smpsw[WMI_DELL_PSW_DISPLAY_CYCLE], + PSWITCH_EVENT_PRESSED); + break; + + case WMI_DELL_HOTKEY_VOLUME_MUTE: + pmf_event_inject(NULL, PMFE_AUDIO_VOLUME_TOGGLE); + break; + + case WMI_DELL_HOTKEY_VOLUME_DOWN: + pmf_event_inject(NULL, PMFE_AUDIO_VOLUME_DOWN); + break; + + case WMI_DELL_HOTKEY_VOLUME_UP: + pmf_event_inject(NULL, PMFE_AUDIO_VOLUME_UP); + break; + + default: + aprint_debug_dev(sc->sc_dev, + "unknown key 0x%02X for event 0x%02X\n", val, evt); + break; + } + +out: + if (buf.Pointer != NULL) + ACPI_FREE(buf.Pointer); + + if (ACPI_FAILURE(rv)) + aprint_error_dev(sc->sc_dev, "failed to get data for " + "event 0x%02X: %s\n", evt, AcpiFormatException(rv)); +}