1 1.5 jruoho /* $NetBSD: wmi_msi.c,v 1.5 2011/02/16 13:15:49 jruoho Exp $ */ 2 1.1 jruoho 3 1.1 jruoho /*- 4 1.1 jruoho * Copyright (c) 2010 The NetBSD Foundation, Inc. 5 1.1 jruoho * All rights reserved. 6 1.1 jruoho * 7 1.1 jruoho * This code is derived from software contributed to The NetBSD Foundation 8 1.1 jruoho * by Jukka Ruohonen. 9 1.1 jruoho * 10 1.1 jruoho * Redistribution and use in source and binary forms, with or without 11 1.1 jruoho * modification, are permitted provided that the following conditions 12 1.1 jruoho * are met: 13 1.1 jruoho * 14 1.1 jruoho * 1. Redistributions of source code must retain the above copyright 15 1.1 jruoho * notice, this list of conditions and the following disclaimer. 16 1.1 jruoho * 2. Redistributions in binary form must reproduce the above copyright 17 1.1 jruoho * notice, this list of conditions and the following disclaimer in the 18 1.1 jruoho * documentation and/or other materials provided with the distribution. 19 1.1 jruoho * 20 1.1 jruoho * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 1.1 jruoho * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 1.1 jruoho * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 1.1 jruoho * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 1.1 jruoho * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 1.1 jruoho * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 1.1 jruoho * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 1.1 jruoho * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 1.1 jruoho * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 1.1 jruoho * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 1.1 jruoho * SUCH DAMAGE. 31 1.1 jruoho */ 32 1.1 jruoho 33 1.1 jruoho #include <sys/cdefs.h> 34 1.5 jruoho __KERNEL_RCSID(0, "$NetBSD: wmi_msi.c,v 1.5 2011/02/16 13:15:49 jruoho Exp $"); 35 1.1 jruoho 36 1.1 jruoho #include <sys/param.h> 37 1.1 jruoho #include <sys/device.h> 38 1.2 jmcneill #include <sys/module.h> 39 1.1 jruoho 40 1.1 jruoho #include <dev/acpi/acpireg.h> 41 1.1 jruoho #include <dev/acpi/acpivar.h> 42 1.1 jruoho #include <dev/acpi/wmi/wmi_acpivar.h> 43 1.1 jruoho 44 1.1 jruoho #define _COMPONENT ACPI_RESOURCE_COMPONENT 45 1.1 jruoho ACPI_MODULE_NAME ("wmi_msi") 46 1.1 jruoho 47 1.1 jruoho #define WMI_MSI_HOTKEY_BRIGHTNESS_UP 0xD0 48 1.1 jruoho #define WMI_MSI_HOTKEY_BRIGHTNESS_DOWN 0xD1 49 1.1 jruoho #define WMI_MSI_HOTKEY_VOLUME_UP 0xD2 50 1.1 jruoho #define WMI_MSI_HOTKEY_VOLUME_DOWN 0xD3 51 1.1 jruoho /* WMI_MSI_HOTKEY_UNKNOWN 0xXXXX */ 52 1.1 jruoho 53 1.1 jruoho #define WMI_MSI_GUID_EVENT "B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2" 54 1.1 jruoho 55 1.1 jruoho struct wmi_msi_softc { 56 1.1 jruoho device_t sc_dev; 57 1.1 jruoho device_t sc_parent; 58 1.1 jruoho }; 59 1.1 jruoho 60 1.1 jruoho static int wmi_msi_match(device_t, cfdata_t, void *); 61 1.1 jruoho static void wmi_msi_attach(device_t, device_t, void *); 62 1.1 jruoho static int wmi_msi_detach(device_t, int); 63 1.1 jruoho static void wmi_msi_notify_handler(ACPI_HANDLE, uint32_t, void *); 64 1.1 jruoho static bool wmi_msi_suspend(device_t, const pmf_qual_t *); 65 1.1 jruoho static bool wmi_msi_resume(device_t, const pmf_qual_t *); 66 1.1 jruoho 67 1.1 jruoho CFATTACH_DECL_NEW(wmimsi, sizeof(struct wmi_msi_softc), 68 1.1 jruoho wmi_msi_match, wmi_msi_attach, wmi_msi_detach, NULL); 69 1.1 jruoho 70 1.1 jruoho static int 71 1.1 jruoho wmi_msi_match(device_t parent, cfdata_t match, void *aux) 72 1.1 jruoho { 73 1.1 jruoho return acpi_wmi_guid_match(parent, WMI_MSI_GUID_EVENT); 74 1.1 jruoho } 75 1.1 jruoho 76 1.1 jruoho static void 77 1.1 jruoho wmi_msi_attach(device_t parent, device_t self, void *aux) 78 1.1 jruoho { 79 1.1 jruoho struct wmi_msi_softc *sc = device_private(self); 80 1.1 jruoho ACPI_STATUS rv; 81 1.1 jruoho 82 1.1 jruoho sc->sc_dev = self; 83 1.1 jruoho sc->sc_parent = parent; 84 1.1 jruoho 85 1.1 jruoho rv = acpi_wmi_event_register(parent, wmi_msi_notify_handler); 86 1.1 jruoho 87 1.1 jruoho if (ACPI_FAILURE(rv)) { 88 1.1 jruoho aprint_error(": failed to install WMI notify handler\n"); 89 1.1 jruoho return; 90 1.1 jruoho } 91 1.1 jruoho 92 1.1 jruoho aprint_naive("\n"); 93 1.1 jruoho aprint_normal(": MSI WMI mappings\n"); 94 1.1 jruoho 95 1.1 jruoho (void)pmf_device_register(self, wmi_msi_suspend, wmi_msi_resume); 96 1.1 jruoho } 97 1.1 jruoho 98 1.1 jruoho static int 99 1.1 jruoho wmi_msi_detach(device_t self, int flags) 100 1.1 jruoho { 101 1.1 jruoho struct wmi_msi_softc *sc = device_private(self); 102 1.1 jruoho device_t parent = sc->sc_parent; 103 1.1 jruoho 104 1.1 jruoho (void)pmf_device_deregister(self); 105 1.1 jruoho (void)acpi_wmi_event_deregister(parent); 106 1.1 jruoho 107 1.1 jruoho return 0; 108 1.1 jruoho } 109 1.1 jruoho 110 1.1 jruoho static bool 111 1.1 jruoho wmi_msi_suspend(device_t self, const pmf_qual_t *qual) 112 1.1 jruoho { 113 1.1 jruoho struct wmi_msi_softc *sc = device_private(self); 114 1.1 jruoho device_t parent = sc->sc_parent; 115 1.1 jruoho 116 1.1 jruoho (void)acpi_wmi_event_deregister(parent); 117 1.1 jruoho 118 1.1 jruoho return true; 119 1.1 jruoho } 120 1.1 jruoho 121 1.1 jruoho static bool 122 1.1 jruoho wmi_msi_resume(device_t self, const pmf_qual_t *qual) 123 1.1 jruoho { 124 1.1 jruoho struct wmi_msi_softc *sc = device_private(self); 125 1.1 jruoho device_t parent = sc->sc_parent; 126 1.1 jruoho 127 1.1 jruoho (void)acpi_wmi_event_register(parent, wmi_msi_notify_handler); 128 1.1 jruoho 129 1.1 jruoho return true; 130 1.1 jruoho } 131 1.1 jruoho 132 1.1 jruoho static void 133 1.1 jruoho wmi_msi_notify_handler(ACPI_HANDLE hdl, uint32_t evt, void *aux) 134 1.1 jruoho { 135 1.1 jruoho struct wmi_msi_softc *sc; 136 1.1 jruoho device_t self = aux; 137 1.1 jruoho ACPI_OBJECT *obj; 138 1.1 jruoho ACPI_BUFFER buf; 139 1.1 jruoho ACPI_STATUS rv; 140 1.1 jruoho uint32_t val; 141 1.1 jruoho 142 1.1 jruoho buf.Pointer = NULL; 143 1.1 jruoho 144 1.1 jruoho sc = device_private(self); 145 1.1 jruoho rv = acpi_wmi_event_get(sc->sc_parent, evt, &buf); 146 1.1 jruoho 147 1.1 jruoho if (ACPI_FAILURE(rv)) 148 1.1 jruoho goto out; 149 1.1 jruoho 150 1.1 jruoho obj = buf.Pointer; 151 1.1 jruoho 152 1.1 jruoho if (obj->Type != ACPI_TYPE_INTEGER) { 153 1.1 jruoho rv = AE_TYPE; 154 1.1 jruoho goto out; 155 1.1 jruoho } 156 1.1 jruoho 157 1.1 jruoho if (obj->Integer.Value > UINT32_MAX) { 158 1.1 jruoho rv = AE_AML_NUMERIC_OVERFLOW; 159 1.1 jruoho goto out; 160 1.1 jruoho } 161 1.1 jruoho 162 1.1 jruoho val = obj->Integer.Value; 163 1.1 jruoho 164 1.1 jruoho switch (val) { 165 1.1 jruoho 166 1.1 jruoho case WMI_MSI_HOTKEY_BRIGHTNESS_DOWN: 167 1.1 jruoho pmf_event_inject(NULL, PMFE_DISPLAY_BRIGHTNESS_DOWN); 168 1.1 jruoho break; 169 1.1 jruoho 170 1.1 jruoho case WMI_MSI_HOTKEY_BRIGHTNESS_UP: 171 1.1 jruoho pmf_event_inject(NULL, PMFE_DISPLAY_BRIGHTNESS_UP); 172 1.1 jruoho break; 173 1.1 jruoho 174 1.1 jruoho case WMI_MSI_HOTKEY_VOLUME_DOWN: 175 1.1 jruoho pmf_event_inject(NULL, PMFE_AUDIO_VOLUME_DOWN); 176 1.1 jruoho break; 177 1.1 jruoho 178 1.1 jruoho case WMI_MSI_HOTKEY_VOLUME_UP: 179 1.1 jruoho pmf_event_inject(NULL, PMFE_AUDIO_VOLUME_UP); 180 1.1 jruoho break; 181 1.1 jruoho 182 1.1 jruoho default: 183 1.1 jruoho aprint_normal_dev(sc->sc_dev, 184 1.1 jruoho "unknown key 0x%02X for event 0x%02X\n", val, evt); 185 1.1 jruoho break; 186 1.1 jruoho } 187 1.1 jruoho 188 1.1 jruoho out: 189 1.1 jruoho if (buf.Pointer != NULL) 190 1.1 jruoho ACPI_FREE(buf.Pointer); 191 1.1 jruoho 192 1.1 jruoho if (ACPI_FAILURE(rv)) 193 1.1 jruoho aprint_error_dev(sc->sc_dev, "failed to get data for " 194 1.1 jruoho "event 0x%02X: %s\n", evt, AcpiFormatException(rv)); 195 1.1 jruoho } 196 1.2 jmcneill 197 1.5 jruoho MODULE(MODULE_CLASS_DRIVER, wmimsi, "acpiwmi"); 198 1.2 jmcneill 199 1.4 jruoho #ifdef _MODULE 200 1.4 jruoho #include "ioconf.c" 201 1.4 jruoho #endif 202 1.2 jmcneill 203 1.2 jmcneill static int 204 1.4 jruoho wmimsi_modcmd(modcmd_t cmd, void *aux) 205 1.2 jmcneill { 206 1.4 jruoho int rv = 0; 207 1.2 jmcneill 208 1.2 jmcneill switch (cmd) { 209 1.2 jmcneill 210 1.2 jmcneill case MODULE_CMD_INIT: 211 1.2 jmcneill 212 1.4 jruoho #ifdef _MODULE 213 1.4 jruoho rv = config_init_component(cfdriver_ioconf_wmimsi, 214 1.4 jruoho cfattach_ioconf_wmimsi, cfdata_ioconf_wmimsi); 215 1.4 jruoho #endif 216 1.4 jruoho break; 217 1.2 jmcneill 218 1.2 jmcneill case MODULE_CMD_FINI: 219 1.2 jmcneill 220 1.4 jruoho #ifdef _MODULE 221 1.4 jruoho rv = config_fini_component(cfdriver_ioconf_wmimsi, 222 1.4 jruoho cfattach_ioconf_wmimsi, cfdata_ioconf_wmimsi); 223 1.4 jruoho #endif 224 1.4 jruoho break; 225 1.2 jmcneill 226 1.2 jmcneill default: 227 1.4 jruoho rv = ENOTTY; 228 1.2 jmcneill } 229 1.4 jruoho 230 1.4 jruoho return rv; 231 1.2 jmcneill } 232