1 /* $OpenBSD: acpisurface.c,v 1.1 2018/06/30 18:15:12 mlarkin Exp $ */ 2 /* 3 * Copyright (c) 2018 Mike Larkin <mlarkin@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 21 #include <dev/acpi/acpireg.h> 22 #include <dev/acpi/acpivar.h> 23 #include <dev/acpi/acpidev.h> 24 #include <dev/acpi/amltypes.h> 25 #include <dev/acpi/dsdt.h> 26 27 #include "audio.h" 28 #include "wskbd.h" 29 30 /* #define ACPISURFACE_DEBUG */ 31 32 #ifdef ACPISURFACE_DEBUG 33 #define DPRINTF(x...) do { printf(x); } while(0) 34 #else 35 #define DPRINTF(x...) 36 #endif /* ACPISURFACE_DEBUG */ 37 38 #define SURFACE_ACCESSORY_REMOVED 0xC8 39 #define SURFACE_WINDOWS_KEY_PRESSED 0xC4 40 #define SURFACE_WINDOWS_KEY_RELEASED 0xC5 41 #define SURFACE_VOLUME_UP_PRESSED 0xC0 42 #define SURFACE_VOLUME_UP_RELEASED 0xC1 43 #define SURFACE_VOLUME_DOWN_PRESSED 0xC2 44 #define SURFACE_VOLUME_DOWN_RELEASED 0xC3 45 #define SURFACE_POWER_BUTTON_PRESSED 0xC6 46 #define SURFACE_POWER_BUTTON_RELEASED 0xC7 47 48 struct acpisurface_softc { 49 struct device sc_dev; 50 51 struct acpiec_softc *sc_ec; 52 struct acpi_softc *sc_acpi; 53 struct aml_node *sc_devnode; 54 }; 55 56 int surface_match(struct device *, void *, void *); 57 void surface_attach(struct device *, struct device *, void *); 58 int surface_hotkey(struct aml_node *, int, void *); 59 60 #if NAUDIO > 0 && NWSKBD > 0 61 extern int wskbd_set_mixervolume(long, long); 62 #endif 63 64 struct cfattach acpisurface_ca = { 65 sizeof(struct acpisurface_softc), surface_match, surface_attach, 66 NULL, NULL 67 }; 68 69 struct cfdriver acpisurface_cd = { 70 NULL, "acpisurface", DV_DULL 71 }; 72 73 const char *acpisurface_hids[] = { 74 "MSHW0040", 75 NULL 76 }; 77 78 int 79 surface_match(struct device *parent, void *match, void *aux) 80 { 81 struct acpi_attach_args *aa = aux; 82 struct cfdata *cf = match; 83 84 if (!acpi_matchhids(aa, acpisurface_hids, cf->cf_driver->cd_name)) 85 return (0); 86 87 return (1); 88 } 89 90 void 91 surface_attach(struct device *parent, struct device *self, void *aux) 92 { 93 struct acpisurface_softc *sc = (struct acpisurface_softc *)self; 94 struct acpi_attach_args *aa = aux; 95 96 sc->sc_acpi = (struct acpi_softc *)parent; 97 sc->sc_devnode = aa->aaa_node; 98 99 printf("\n"); 100 101 /* Run surface_hotkey on button presses */ 102 aml_register_notify(sc->sc_devnode, aa->aaa_dev, 103 surface_hotkey, sc, ACPIDEV_NOPOLL); 104 } 105 106 int 107 surface_hotkey(struct aml_node *node, int notify_type, void *arg) 108 { 109 struct acpisurface_softc *sc = arg; 110 111 switch (notify_type) { 112 case SURFACE_ACCESSORY_REMOVED: 113 DPRINTF("%s: accessory removed\n", __func__); 114 break; 115 case SURFACE_VOLUME_UP_PRESSED: 116 DPRINTF("%s: volume up pressed\n", __func__); 117 #if NAUDIO > 0 && NWSKBD > 0 118 wskbd_set_mixervolume(1, 10); 119 #endif 120 break; 121 case SURFACE_VOLUME_UP_RELEASED: 122 DPRINTF("%s: volume up released\n", __func__); 123 break; 124 case SURFACE_VOLUME_DOWN_PRESSED: 125 DPRINTF("%s: volume down pressed\n", __func__); 126 #if NAUDIO > 0 && NWSKBD > 0 127 wskbd_set_mixervolume(-1, 10); 128 #endif 129 break; 130 case SURFACE_VOLUME_DOWN_RELEASED: 131 DPRINTF("%s: volume down released\n", __func__); 132 break; 133 case SURFACE_POWER_BUTTON_PRESSED: 134 DPRINTF("%s: power button pressed\n", __func__); 135 break; 136 case SURFACE_POWER_BUTTON_RELEASED: 137 DPRINTF("%s: power button released\n", __func__); 138 acpi_addtask(sc->sc_acpi, acpi_powerdown_task, 139 sc->sc_acpi, 0); 140 break; 141 case SURFACE_WINDOWS_KEY_PRESSED: 142 DPRINTF("%s: windows key pressed\n", __func__); 143 break; 144 case SURFACE_WINDOWS_KEY_RELEASED: 145 DPRINTF("%s: windows key released\n", __func__); 146 break; 147 default: 148 DPRINTF("%s: unknown notification 0x%x\n", __func__, 149 notify_type); 150 } 151 152 return (0); 153 } 154