xref: /openbsd/sys/dev/acpi/acpisurface.c (revision 674f03e5)
1 /*	$OpenBSD: acpisurface.c,v 1.3 2024/08/15 17:30:40 deraadt 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 const 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
surface_match(struct device * parent,void * match,void * aux)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
surface_attach(struct device * parent,struct device * self,void * aux)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
surface_hotkey(struct aml_node * node,int notify_type,void * arg)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