Line data Source code
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 0 : surface_match(struct device *parent, void *match, void *aux)
80 : {
81 0 : struct acpi_attach_args *aa = aux;
82 0 : struct cfdata *cf = match;
83 :
84 0 : if (!acpi_matchhids(aa, acpisurface_hids, cf->cf_driver->cd_name))
85 0 : return (0);
86 :
87 0 : return (1);
88 0 : }
89 :
90 : void
91 0 : surface_attach(struct device *parent, struct device *self, void *aux)
92 : {
93 0 : struct acpisurface_softc *sc = (struct acpisurface_softc *)self;
94 0 : struct acpi_attach_args *aa = aux;
95 :
96 0 : sc->sc_acpi = (struct acpi_softc *)parent;
97 0 : sc->sc_devnode = aa->aaa_node;
98 :
99 0 : printf("\n");
100 :
101 : /* Run surface_hotkey on button presses */
102 0 : aml_register_notify(sc->sc_devnode, aa->aaa_dev,
103 0 : surface_hotkey, sc, ACPIDEV_NOPOLL);
104 0 : }
105 :
106 : int
107 0 : surface_hotkey(struct aml_node *node, int notify_type, void *arg)
108 : {
109 0 : struct acpisurface_softc *sc = arg;
110 :
111 0 : 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 0 : wskbd_set_mixervolume(1, 10);
119 : #endif
120 0 : 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 0 : wskbd_set_mixervolume(-1, 10);
128 : #endif
129 0 : 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 0 : acpi_addtask(sc->sc_acpi, acpi_powerdown_task,
139 0 : sc->sc_acpi, 0);
140 0 : 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 0 : return (0);
153 : }
|