1*2bcc3febSjca /* $OpenBSD: acpihid.c,v 1.4 2022/05/29 22:03:44 jca Exp $ */
2fa9d1ef8Sjcs /*
3fa9d1ef8Sjcs * ACPI HID event and 5-button array driver
4fa9d1ef8Sjcs *
5fa9d1ef8Sjcs * Copyright (c) 2018, 2020 joshua stein <jcs@jcs.org>
6fa9d1ef8Sjcs *
7fa9d1ef8Sjcs * Permission to use, copy, modify, and distribute this software for any
8fa9d1ef8Sjcs * purpose with or without fee is hereby granted, provided that the above
9fa9d1ef8Sjcs * copyright notice and this permission notice appear in all copies.
10fa9d1ef8Sjcs *
11fa9d1ef8Sjcs * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12fa9d1ef8Sjcs * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13fa9d1ef8Sjcs * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14fa9d1ef8Sjcs * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15fa9d1ef8Sjcs * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16fa9d1ef8Sjcs * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17fa9d1ef8Sjcs * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18fa9d1ef8Sjcs */
19fa9d1ef8Sjcs
20fa9d1ef8Sjcs #include <sys/param.h>
21fa9d1ef8Sjcs #include <sys/signalvar.h>
22fa9d1ef8Sjcs #include <sys/systm.h>
23fa9d1ef8Sjcs #include <sys/device.h>
24fa9d1ef8Sjcs #include <sys/malloc.h>
25fa9d1ef8Sjcs
26fa9d1ef8Sjcs #include <machine/bus.h>
27fa9d1ef8Sjcs #include <machine/apmvar.h>
28fa9d1ef8Sjcs
29fa9d1ef8Sjcs #include <dev/acpi/acpireg.h>
30fa9d1ef8Sjcs #include <dev/acpi/acpivar.h>
31fa9d1ef8Sjcs #include <dev/acpi/acpidev.h>
32fa9d1ef8Sjcs #include <dev/acpi/amltypes.h>
33fa9d1ef8Sjcs #include <dev/acpi/dsdt.h>
34fa9d1ef8Sjcs
35fa9d1ef8Sjcs #include "audio.h"
36fa9d1ef8Sjcs #include "wskbd.h"
37fa9d1ef8Sjcs
38fa9d1ef8Sjcs /* #define ACPIHID_DEBUG */
39fa9d1ef8Sjcs
40fa9d1ef8Sjcs #ifdef ACPIHID_DEBUG
41fa9d1ef8Sjcs #define DPRINTF(x) printf x
42fa9d1ef8Sjcs #else
43fa9d1ef8Sjcs #define DPRINTF(x)
44fa9d1ef8Sjcs #endif
45fa9d1ef8Sjcs
46fa9d1ef8Sjcs struct acpihid_softc {
47fa9d1ef8Sjcs struct device sc_dev;
48fa9d1ef8Sjcs
49fa9d1ef8Sjcs bus_space_tag_t sc_iot;
50fa9d1ef8Sjcs bus_space_handle_t sc_ioh;
51fa9d1ef8Sjcs
52fa9d1ef8Sjcs struct acpi_softc *sc_acpi;
53fa9d1ef8Sjcs struct aml_node *sc_devnode;
54fa9d1ef8Sjcs int sc_5_button;
55fa9d1ef8Sjcs
56fa9d1ef8Sjcs /*
57fa9d1ef8Sjcs * HEBC v1
58fa9d1ef8Sjcs * 0 - Rotation Lock, Num Lock, Home, End, Page Up, Page Down
59fa9d1ef8Sjcs * 1 - Wireless Radio Control
60fa9d1ef8Sjcs * 2 - System Power Down
61fa9d1ef8Sjcs * 3 - System Hibernate
62fa9d1ef8Sjcs * 4 - System Sleep/ System Wake
63fa9d1ef8Sjcs * 5 - Scan Next Track
64fa9d1ef8Sjcs * 6 - Scan Previous Track
65fa9d1ef8Sjcs * 7 - Stop
66fa9d1ef8Sjcs * 8 - Play/Pause
67fa9d1ef8Sjcs * 9 - Mute
68fa9d1ef8Sjcs * 10 - Volume Increment
69fa9d1ef8Sjcs * 11 - Volume Decrement
70fa9d1ef8Sjcs * 12 - Display Brightness Increment
71fa9d1ef8Sjcs * 13 - Display Brightness Decrement
72fa9d1ef8Sjcs * 14 - Lock Tablet
73fa9d1ef8Sjcs * 15 - Release Tablet
74fa9d1ef8Sjcs * 16 - Toggle Bezel
75fa9d1ef8Sjcs * 17 - 5 button array
76fa9d1ef8Sjcs * 18-31 - reserved
77fa9d1ef8Sjcs *
78fa9d1ef8Sjcs * HEBC v2
79fa9d1ef8Sjcs * 0-17 - Same as v1 version
80fa9d1ef8Sjcs * 18 – Power Button
81fa9d1ef8Sjcs * 19 - W Home Button
82fa9d1ef8Sjcs * 20 - Volume Up Button
83fa9d1ef8Sjcs * 21 - Volume Down Button
84fa9d1ef8Sjcs * 22 – Rotation Lock Button
85fa9d1ef8Sjcs * 23-31 – reserved
86fa9d1ef8Sjcs */
87fa9d1ef8Sjcs uint32_t sc_dsm_fn_mask;
88fa9d1ef8Sjcs };
89fa9d1ef8Sjcs
90fa9d1ef8Sjcs enum {
91fa9d1ef8Sjcs ACPIHID_FUNC_INVALID,
92fa9d1ef8Sjcs ACPIHID_FUNC_BTNL,
93fa9d1ef8Sjcs ACPIHID_FUNC_HDMM,
94fa9d1ef8Sjcs ACPIHID_FUNC_HDSM,
95fa9d1ef8Sjcs ACPIHID_FUNC_HDEM,
96fa9d1ef8Sjcs ACPIHID_FUNC_BTNS,
97fa9d1ef8Sjcs ACPIHID_FUNC_BTNE,
98fa9d1ef8Sjcs ACPIHID_FUNC_HEBC_V1,
99fa9d1ef8Sjcs ACPIHID_FUNC_VGBS,
100fa9d1ef8Sjcs ACPIHID_FUNC_HEBC_V2,
101fa9d1ef8Sjcs ACPIHID_FUNC_MAX,
102fa9d1ef8Sjcs };
103fa9d1ef8Sjcs
104fa9d1ef8Sjcs static const char *acpihid_dsm_funcs[] = {
105fa9d1ef8Sjcs NULL,
106fa9d1ef8Sjcs "BTNL",
107fa9d1ef8Sjcs "HDMM",
108fa9d1ef8Sjcs "HDSM",
109fa9d1ef8Sjcs "HDEM",
110fa9d1ef8Sjcs "BTNS",
111fa9d1ef8Sjcs "BTNE",
112fa9d1ef8Sjcs "HEBC",
113fa9d1ef8Sjcs "VGBS",
114fa9d1ef8Sjcs "HEBC",
115fa9d1ef8Sjcs };
116fa9d1ef8Sjcs
117fa9d1ef8Sjcs int acpihid_match(struct device *, void *, void *);
118fa9d1ef8Sjcs void acpihid_attach(struct device *, struct device *, void *);
119fa9d1ef8Sjcs void acpihid_init_dsm(struct acpihid_softc *);
120fa9d1ef8Sjcs int acpihid_button_array_enable(struct acpihid_softc *, int);
121fa9d1ef8Sjcs int acpihid_eval(struct acpihid_softc *, int, int64_t, int64_t *);
122fa9d1ef8Sjcs int acpihid_notify(struct aml_node *, int, void *);
123fa9d1ef8Sjcs
124fa9d1ef8Sjcs #if NAUDIO > 0 && NWSKBD > 0
125fa9d1ef8Sjcs extern int wskbd_set_mixervolume(long, long);
126fa9d1ef8Sjcs #endif
127fa9d1ef8Sjcs
128471aeecfSnaddy const struct cfattach acpihid_ca = {
129fa9d1ef8Sjcs sizeof(struct acpihid_softc),
130fa9d1ef8Sjcs acpihid_match,
131fa9d1ef8Sjcs acpihid_attach,
132fa9d1ef8Sjcs NULL,
133fa9d1ef8Sjcs NULL,
134fa9d1ef8Sjcs };
135fa9d1ef8Sjcs
136fa9d1ef8Sjcs struct cfdriver acpihid_cd = {
137fa9d1ef8Sjcs NULL, "acpihid", DV_DULL
138fa9d1ef8Sjcs };
139fa9d1ef8Sjcs
140fa9d1ef8Sjcs const char *acpihid_hids[] = {
141fa9d1ef8Sjcs "INT33D5",
142fa9d1ef8Sjcs NULL
143fa9d1ef8Sjcs };
144fa9d1ef8Sjcs
145fa9d1ef8Sjcs /* eeec56b3-4442-408f-a792-4edd4d758054 */
146fa9d1ef8Sjcs static uint8_t acpihid_guid[] = {
147fa9d1ef8Sjcs 0xB3, 0x56, 0xEC, 0xEE, 0x42, 0x44, 0x8F, 0x40,
148fa9d1ef8Sjcs 0xA7, 0x92, 0x4E, 0xDD, 0x4D, 0x75, 0x80, 0x54,
149fa9d1ef8Sjcs };
150fa9d1ef8Sjcs
151fa9d1ef8Sjcs int
acpihid_match(struct device * parent,void * match,void * aux)152fa9d1ef8Sjcs acpihid_match(struct device *parent, void *match, void *aux)
153fa9d1ef8Sjcs {
154fa9d1ef8Sjcs struct acpi_attach_args *aa = aux;
155fa9d1ef8Sjcs struct cfdata *cf = match;
156fa9d1ef8Sjcs
157fa9d1ef8Sjcs return (acpi_matchhids(aa, acpihid_hids, cf->cf_driver->cd_name));
158fa9d1ef8Sjcs }
159fa9d1ef8Sjcs
160fa9d1ef8Sjcs void
acpihid_attach(struct device * parent,struct device * self,void * aux)161fa9d1ef8Sjcs acpihid_attach(struct device *parent, struct device *self, void *aux)
162fa9d1ef8Sjcs {
163fa9d1ef8Sjcs struct acpihid_softc *sc = (struct acpihid_softc *)self;
164fa9d1ef8Sjcs struct acpi_attach_args *aa = aux;
165fa9d1ef8Sjcs uint64_t val;
166fa9d1ef8Sjcs
167fa9d1ef8Sjcs sc->sc_acpi = (struct acpi_softc *)parent;
168fa9d1ef8Sjcs sc->sc_devnode = aa->aaa_node;
169fa9d1ef8Sjcs
170fa9d1ef8Sjcs printf(": %s", sc->sc_devnode->name);
171fa9d1ef8Sjcs
172fa9d1ef8Sjcs acpihid_init_dsm(sc);
173fa9d1ef8Sjcs
174fa9d1ef8Sjcs if (acpihid_eval(sc, ACPIHID_FUNC_HDMM, 0, &val) != 0) {
175fa9d1ef8Sjcs printf(", failed reading mode\n");
176fa9d1ef8Sjcs return;
177fa9d1ef8Sjcs } else if (val != 0) {
178fa9d1ef8Sjcs printf(", unknown mode %lld\n", val);
179fa9d1ef8Sjcs return;
180fa9d1ef8Sjcs }
181fa9d1ef8Sjcs
182fa9d1ef8Sjcs if ((acpihid_eval(sc, ACPIHID_FUNC_HEBC_V2, 0, &val) == 0 &&
183fa9d1ef8Sjcs (val & 0x60000)) ||
184fa9d1ef8Sjcs (acpihid_eval(sc, ACPIHID_FUNC_HEBC_V1, 0, &val) == 0 &&
185fa9d1ef8Sjcs (val & 0x20000)))
186fa9d1ef8Sjcs sc->sc_5_button = 1;
187fa9d1ef8Sjcs
188fa9d1ef8Sjcs aml_register_notify(sc->sc_devnode, aa->aaa_dev, acpihid_notify,
189fa9d1ef8Sjcs sc, ACPIDEV_NOPOLL);
190fa9d1ef8Sjcs
191fa9d1ef8Sjcs /* enable hid set */
192fa9d1ef8Sjcs acpihid_eval(sc, ACPIHID_FUNC_HDSM, 1, NULL);
193fa9d1ef8Sjcs
194fa9d1ef8Sjcs if (sc->sc_5_button) {
195fa9d1ef8Sjcs acpihid_button_array_enable(sc, 1);
196fa9d1ef8Sjcs
197fa9d1ef8Sjcs if (acpihid_eval(sc, ACPIHID_FUNC_BTNL, 0, NULL) == 0)
198fa9d1ef8Sjcs printf(", 5 button array");
199fa9d1ef8Sjcs else
200fa9d1ef8Sjcs printf(", failed enabling HID power button");
201fa9d1ef8Sjcs }
202fa9d1ef8Sjcs
203fa9d1ef8Sjcs printf("\n");
204fa9d1ef8Sjcs }
205fa9d1ef8Sjcs
206fa9d1ef8Sjcs void
acpihid_init_dsm(struct acpihid_softc * sc)207fa9d1ef8Sjcs acpihid_init_dsm(struct acpihid_softc *sc)
208fa9d1ef8Sjcs {
209fa9d1ef8Sjcs struct aml_value cmd[4], res;
210fa9d1ef8Sjcs
211fa9d1ef8Sjcs sc->sc_dsm_fn_mask = 0;
212fa9d1ef8Sjcs
213fa9d1ef8Sjcs if (!aml_searchname(sc->sc_devnode, "_DSM")) {
214fa9d1ef8Sjcs DPRINTF(("%s: no _DSM support\n", sc->sc_dev.dv_xname));
215fa9d1ef8Sjcs return;
216fa9d1ef8Sjcs }
217fa9d1ef8Sjcs
218fa9d1ef8Sjcs bzero(&cmd, sizeof(cmd));
219fa9d1ef8Sjcs cmd[0].type = AML_OBJTYPE_BUFFER;
220fa9d1ef8Sjcs cmd[0].v_buffer = (uint8_t *)&acpihid_guid;
221fa9d1ef8Sjcs cmd[0].length = sizeof(acpihid_guid);
222fa9d1ef8Sjcs /* rev */
223fa9d1ef8Sjcs cmd[1].type = AML_OBJTYPE_INTEGER;
224fa9d1ef8Sjcs cmd[1].v_integer = 1;
225fa9d1ef8Sjcs cmd[1].length = 1;
226fa9d1ef8Sjcs /* func */
227fa9d1ef8Sjcs cmd[2].type = AML_OBJTYPE_INTEGER;
228fa9d1ef8Sjcs cmd[2].v_integer = 0;
229fa9d1ef8Sjcs cmd[2].length = 1;
230fa9d1ef8Sjcs /* not used */
231fa9d1ef8Sjcs cmd[3].type = AML_OBJTYPE_BUFFER;
232fa9d1ef8Sjcs cmd[3].length = 0;
233fa9d1ef8Sjcs
234fa9d1ef8Sjcs if (aml_evalname(acpi_softc, sc->sc_devnode, "_DSM", 4, cmd,
235fa9d1ef8Sjcs &res)) {
236fa9d1ef8Sjcs printf("%s: eval of _DSM at %s failed\n",
237fa9d1ef8Sjcs sc->sc_dev.dv_xname, aml_nodename(sc->sc_devnode));
238fa9d1ef8Sjcs return;
239fa9d1ef8Sjcs }
240fa9d1ef8Sjcs
241fa9d1ef8Sjcs if (res.type != AML_OBJTYPE_BUFFER) {
242fa9d1ef8Sjcs printf("%s: bad _DSM result at %s: %d\n", sc->sc_dev.dv_xname,
243fa9d1ef8Sjcs aml_nodename(sc->sc_devnode), res.type);
244fa9d1ef8Sjcs aml_freevalue(&res);
245fa9d1ef8Sjcs return;
246fa9d1ef8Sjcs }
247fa9d1ef8Sjcs
248fa9d1ef8Sjcs sc->sc_dsm_fn_mask = *res.v_buffer;
249fa9d1ef8Sjcs DPRINTF(("%s: _DSM function mask 0x%x\n", sc->sc_dev.dv_xname,
250fa9d1ef8Sjcs sc->sc_dsm_fn_mask));
251fa9d1ef8Sjcs
252fa9d1ef8Sjcs aml_freevalue(&res);
253fa9d1ef8Sjcs }
254fa9d1ef8Sjcs
255fa9d1ef8Sjcs int
acpihid_eval(struct acpihid_softc * sc,int idx,int64_t arg,int64_t * ret)256fa9d1ef8Sjcs acpihid_eval(struct acpihid_softc *sc, int idx, int64_t arg, int64_t *ret)
257fa9d1ef8Sjcs {
258fa9d1ef8Sjcs struct aml_value cmd[4], pkg, *ppkg;
259fa9d1ef8Sjcs int64_t tret;
260fa9d1ef8Sjcs const char *dsm_func;
261fa9d1ef8Sjcs
262fa9d1ef8Sjcs if (idx <= ACPIHID_FUNC_INVALID || idx >= ACPIHID_FUNC_MAX) {
263fa9d1ef8Sjcs printf("%s: _DSM func index %d out of bounds\n",
264fa9d1ef8Sjcs sc->sc_dev.dv_xname, idx);
265fa9d1ef8Sjcs return 1;
266fa9d1ef8Sjcs }
267fa9d1ef8Sjcs
268fa9d1ef8Sjcs dsm_func = acpihid_dsm_funcs[idx];
269fa9d1ef8Sjcs
270fa9d1ef8Sjcs DPRINTF(("%s: executing _DSM %s\n", sc->sc_dev.dv_xname, dsm_func));
271fa9d1ef8Sjcs
272fa9d1ef8Sjcs if (!(sc->sc_dsm_fn_mask & idx)) {
273fa9d1ef8Sjcs DPRINTF(("%s: _DSM mask does not support %s (%d), executing "
274fa9d1ef8Sjcs "directly\n", sc->sc_dev.dv_xname, dsm_func, idx));
275fa9d1ef8Sjcs goto eval_direct;
276fa9d1ef8Sjcs }
277fa9d1ef8Sjcs
278fa9d1ef8Sjcs bzero(&pkg, sizeof(pkg));
279fa9d1ef8Sjcs pkg.type = AML_OBJTYPE_INTEGER;
280fa9d1ef8Sjcs pkg.v_integer = arg;
281fa9d1ef8Sjcs pkg.length = 1;
282fa9d1ef8Sjcs ppkg = &pkg;
283fa9d1ef8Sjcs
284fa9d1ef8Sjcs bzero(&cmd, sizeof(cmd));
285fa9d1ef8Sjcs cmd[0].type = AML_OBJTYPE_BUFFER;
286fa9d1ef8Sjcs cmd[0].v_buffer = (uint8_t *)&acpihid_guid;
287fa9d1ef8Sjcs cmd[0].length = sizeof(acpihid_guid);
288fa9d1ef8Sjcs /* rev */
289fa9d1ef8Sjcs cmd[1].type = AML_OBJTYPE_INTEGER;
290fa9d1ef8Sjcs cmd[1].v_integer = 1;
291fa9d1ef8Sjcs cmd[1].length = 1;
292fa9d1ef8Sjcs /* func */
293fa9d1ef8Sjcs cmd[2].type = AML_OBJTYPE_INTEGER;
294fa9d1ef8Sjcs cmd[2].v_integer = idx;
295fa9d1ef8Sjcs cmd[2].length = 1;
296fa9d1ef8Sjcs /* arg */
297fa9d1ef8Sjcs cmd[3].type = AML_OBJTYPE_PACKAGE;
298fa9d1ef8Sjcs cmd[3].length = 1;
299fa9d1ef8Sjcs cmd[3].v_package = &ppkg;
300fa9d1ef8Sjcs
301fa9d1ef8Sjcs if (aml_evalinteger(acpi_softc, sc->sc_devnode, "_DSM", 4, cmd,
302fa9d1ef8Sjcs &tret)) {
303fa9d1ef8Sjcs DPRINTF(("%s: _DSM %s failed\n", sc->sc_dev.dv_xname,
304fa9d1ef8Sjcs dsm_func));
305fa9d1ef8Sjcs return 1;
306fa9d1ef8Sjcs }
307fa9d1ef8Sjcs
308fa9d1ef8Sjcs DPRINTF(("%s: _DSM eval of %s succeeded\n", sc->sc_dev.dv_xname,
309fa9d1ef8Sjcs dsm_func));
310fa9d1ef8Sjcs
311fa9d1ef8Sjcs if (ret != NULL)
312fa9d1ef8Sjcs *ret = tret;
313fa9d1ef8Sjcs
314fa9d1ef8Sjcs return 0;
315fa9d1ef8Sjcs
316fa9d1ef8Sjcs eval_direct:
317fa9d1ef8Sjcs cmd[0].type = AML_OBJTYPE_INTEGER;
318fa9d1ef8Sjcs cmd[0].v_integer = arg;
319fa9d1ef8Sjcs cmd[0].length = 1;
320fa9d1ef8Sjcs
321fa9d1ef8Sjcs if (aml_evalinteger(acpi_softc, sc->sc_devnode, dsm_func, 1, cmd,
322fa9d1ef8Sjcs &tret) != 0) {
323fa9d1ef8Sjcs printf("%s: exec of %s failed\n", sc->sc_dev.dv_xname,
324fa9d1ef8Sjcs dsm_func);
325fa9d1ef8Sjcs return 1;
326fa9d1ef8Sjcs }
327fa9d1ef8Sjcs
328fa9d1ef8Sjcs if (ret != NULL)
329fa9d1ef8Sjcs *ret = tret;
330fa9d1ef8Sjcs
331fa9d1ef8Sjcs return 0;
332fa9d1ef8Sjcs }
333fa9d1ef8Sjcs
334fa9d1ef8Sjcs int
acpihid_button_array_enable(struct acpihid_softc * sc,int enable)335fa9d1ef8Sjcs acpihid_button_array_enable(struct acpihid_softc *sc, int enable)
336fa9d1ef8Sjcs {
337fa9d1ef8Sjcs int64_t cap;
338fa9d1ef8Sjcs
339fa9d1ef8Sjcs if (aml_evalinteger(acpi_softc, sc->sc_devnode, "BTNC", 0, NULL,
340fa9d1ef8Sjcs &cap) != 0) {
341fa9d1ef8Sjcs printf("%s: failed getting button array capability\n",
342fa9d1ef8Sjcs sc->sc_dev.dv_xname);
343fa9d1ef8Sjcs return 1;
344fa9d1ef8Sjcs }
345fa9d1ef8Sjcs
346fa9d1ef8Sjcs if (acpihid_eval(sc, ACPIHID_FUNC_BTNE, enable ? cap : 1, NULL) != 0) {
347fa9d1ef8Sjcs printf("%s: failed enabling button array\n",
348fa9d1ef8Sjcs sc->sc_dev.dv_xname);
349fa9d1ef8Sjcs return 1;
350fa9d1ef8Sjcs }
351fa9d1ef8Sjcs
352fa9d1ef8Sjcs return 0;
353fa9d1ef8Sjcs }
354fa9d1ef8Sjcs
355fa9d1ef8Sjcs int
acpihid_notify(struct aml_node * node,int notify_type,void * arg)356fa9d1ef8Sjcs acpihid_notify(struct aml_node *node, int notify_type, void *arg)
357fa9d1ef8Sjcs {
358a2a1e600Sjcs #ifdef ACPIHID_DEBUG
359fa9d1ef8Sjcs struct acpihid_softc *sc = arg;
360fa9d1ef8Sjcs
361fa9d1ef8Sjcs DPRINTF(("%s: %s: %.2x\n", sc->sc_dev.dv_xname, __func__,
362fa9d1ef8Sjcs notify_type));
363fa9d1ef8Sjcs #endif
364fa9d1ef8Sjcs
365fa9d1ef8Sjcs switch (notify_type) {
366fa9d1ef8Sjcs case 0xc2: /* left meta press */
367fa9d1ef8Sjcs break;
368fa9d1ef8Sjcs case 0xc3: /* left meta release */
369fa9d1ef8Sjcs break;
370fa9d1ef8Sjcs case 0xc4: /* volume up press */
371fa9d1ef8Sjcs #if NAUDIO > 0 && NWSKBD > 0
372fa9d1ef8Sjcs wskbd_set_mixervolume(1, 1);
373fa9d1ef8Sjcs #endif
374fa9d1ef8Sjcs break;
375fa9d1ef8Sjcs case 0xc5: /* volume up release */
376fa9d1ef8Sjcs break;
377fa9d1ef8Sjcs case 0xc6: /* volume down press */
378fa9d1ef8Sjcs #if NAUDIO > 0 && NWSKBD > 0
379fa9d1ef8Sjcs wskbd_set_mixervolume(-1, 1);
380fa9d1ef8Sjcs #endif
381fa9d1ef8Sjcs break;
382fa9d1ef8Sjcs case 0xc7: /* volume down release */
383fa9d1ef8Sjcs break;
384fa9d1ef8Sjcs case 0xc8: /* rotate lock toggle press */
385fa9d1ef8Sjcs break;
386fa9d1ef8Sjcs case 0xc9: /* rotate lock toggle release */
387fa9d1ef8Sjcs break;
388fa9d1ef8Sjcs case 0xce: /* power button press */
389fa9d1ef8Sjcs break;
390fa9d1ef8Sjcs case 0xcf: /* power button release */
391fa9d1ef8Sjcs break;
392fa9d1ef8Sjcs default:
393a2a1e600Sjcs DPRINTF(("%s: unhandled button 0x%x\n", sc->sc_dev.dv_xname,
394a2a1e600Sjcs notify_type));
395fa9d1ef8Sjcs }
396fa9d1ef8Sjcs
397fa9d1ef8Sjcs return 0;
398fa9d1ef8Sjcs }
399