1461a98a2SAlexander Motin /*-
2461a98a2SAlexander Motin * Copyright (c) 2012 Alexander Motin <mav@FreeBSD.org>
3461a98a2SAlexander Motin * All rights reserved.
4461a98a2SAlexander Motin *
5461a98a2SAlexander Motin * Redistribution and use in source and binary forms, with or without
6461a98a2SAlexander Motin * modification, are permitted provided that the following conditions
7461a98a2SAlexander Motin * are met:
8461a98a2SAlexander Motin * 1. Redistributions of source code must retain the above copyright
9461a98a2SAlexander Motin * notice, this list of conditions and the following disclaimer.
10461a98a2SAlexander Motin * 2. Redistributions in binary form must reproduce the above copyright
11461a98a2SAlexander Motin * notice, this list of conditions and the following disclaimer in the
12461a98a2SAlexander Motin * documentation and/or other materials provided with the distribution.
13461a98a2SAlexander Motin *
14461a98a2SAlexander Motin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15461a98a2SAlexander Motin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16461a98a2SAlexander Motin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17461a98a2SAlexander Motin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18461a98a2SAlexander Motin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19461a98a2SAlexander Motin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20461a98a2SAlexander Motin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21461a98a2SAlexander Motin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22461a98a2SAlexander Motin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23461a98a2SAlexander Motin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24461a98a2SAlexander Motin * SUCH DAMAGE.
25461a98a2SAlexander Motin */
26461a98a2SAlexander Motin
27461a98a2SAlexander Motin #include <sys/cdefs.h>
28461a98a2SAlexander Motin #include "opt_acpi.h"
295e41194bSVladimir Kondratyev #include "opt_evdev.h"
30461a98a2SAlexander Motin #include <sys/param.h>
31461a98a2SAlexander Motin #include <sys/conf.h>
32461a98a2SAlexander Motin #include <sys/uio.h>
33461a98a2SAlexander Motin #include <sys/proc.h>
34461a98a2SAlexander Motin #include <sys/kernel.h>
35461a98a2SAlexander Motin #include <sys/bus.h>
36461a98a2SAlexander Motin #include <sys/sbuf.h>
37461a98a2SAlexander Motin #include <sys/module.h>
38461a98a2SAlexander Motin #include <sys/sysctl.h>
39461a98a2SAlexander Motin
40461a98a2SAlexander Motin #include <contrib/dev/acpica/include/acpi.h>
41461a98a2SAlexander Motin #include <contrib/dev/acpica/include/accommon.h>
42461a98a2SAlexander Motin #include <dev/acpica/acpivar.h>
43461a98a2SAlexander Motin #include "acpi_wmi_if.h"
44461a98a2SAlexander Motin
45f134662aSVladimir Kondratyev #include <dev/backlight/backlight.h>
46f134662aSVladimir Kondratyev #include "backlight_if.h"
47f134662aSVladimir Kondratyev
485e41194bSVladimir Kondratyev #ifdef EVDEV_SUPPORT
495e41194bSVladimir Kondratyev #include <dev/evdev/input.h>
505e41194bSVladimir Kondratyev #include <dev/evdev/evdev.h>
515e41194bSVladimir Kondratyev #define NO_KEY KEY_RESERVED
525e41194bSVladimir Kondratyev #endif
535e41194bSVladimir Kondratyev
54461a98a2SAlexander Motin #define _COMPONENT ACPI_OEM
55461a98a2SAlexander Motin ACPI_MODULE_NAME("ASUS-WMI")
56461a98a2SAlexander Motin
57461a98a2SAlexander Motin #define ACPI_ASUS_WMI_MGMT_GUID "97845ED0-4E6D-11DE-8A39-0800200C9A66"
58461a98a2SAlexander Motin #define ACPI_ASUS_WMI_EVENT_GUID "0B3CBB35-E3C2-45ED-91C2-4C5A6D195D1C"
59461a98a2SAlexander Motin #define ACPI_EEEPC_WMI_EVENT_GUID "ABBC0F72-8EA1-11D1-00A0-C90629100000"
60461a98a2SAlexander Motin
61461a98a2SAlexander Motin /* WMI Methods */
62461a98a2SAlexander Motin #define ASUS_WMI_METHODID_SPEC 0x43455053
63461a98a2SAlexander Motin #define ASUS_WMI_METHODID_SFUN 0x4E554653
64461a98a2SAlexander Motin #define ASUS_WMI_METHODID_DSTS 0x53544344
65461a98a2SAlexander Motin #define ASUS_WMI_METHODID_DSTS2 0x53545344
66461a98a2SAlexander Motin #define ASUS_WMI_METHODID_DEVS 0x53564544
67461a98a2SAlexander Motin #define ASUS_WMI_METHODID_INIT 0x54494E49
68461a98a2SAlexander Motin #define ASUS_WMI_METHODID_HKEY 0x59454B48
69461a98a2SAlexander Motin
70461a98a2SAlexander Motin #define ASUS_WMI_UNSUPPORTED_METHOD 0xFFFFFFFE
71461a98a2SAlexander Motin
72461a98a2SAlexander Motin /* Wireless */
73461a98a2SAlexander Motin #define ASUS_WMI_DEVID_HW_SWITCH 0x00010001
74461a98a2SAlexander Motin #define ASUS_WMI_DEVID_WIRELESS_LED 0x00010002
75461a98a2SAlexander Motin #define ASUS_WMI_DEVID_CWAP 0x00010003
76461a98a2SAlexander Motin #define ASUS_WMI_DEVID_WLAN 0x00010011
77461a98a2SAlexander Motin #define ASUS_WMI_DEVID_BLUETOOTH 0x00010013
78461a98a2SAlexander Motin #define ASUS_WMI_DEVID_GPS 0x00010015
79461a98a2SAlexander Motin #define ASUS_WMI_DEVID_WIMAX 0x00010017
80461a98a2SAlexander Motin #define ASUS_WMI_DEVID_WWAN3G 0x00010019
81461a98a2SAlexander Motin #define ASUS_WMI_DEVID_UWB 0x00010021
82461a98a2SAlexander Motin
83461a98a2SAlexander Motin /* LEDs */
84461a98a2SAlexander Motin #define ASUS_WMI_DEVID_LED1 0x00020011
85461a98a2SAlexander Motin #define ASUS_WMI_DEVID_LED2 0x00020012
86461a98a2SAlexander Motin #define ASUS_WMI_DEVID_LED3 0x00020013
87461a98a2SAlexander Motin #define ASUS_WMI_DEVID_LED4 0x00020014
88461a98a2SAlexander Motin #define ASUS_WMI_DEVID_LED5 0x00020015
89461a98a2SAlexander Motin #define ASUS_WMI_DEVID_LED6 0x00020016
90461a98a2SAlexander Motin
91461a98a2SAlexander Motin /* Backlight and Brightness */
92461a98a2SAlexander Motin #define ASUS_WMI_DEVID_BACKLIGHT 0x00050011
93461a98a2SAlexander Motin #define ASUS_WMI_DEVID_BRIGHTNESS 0x00050012
94461a98a2SAlexander Motin #define ASUS_WMI_DEVID_KBD_BACKLIGHT 0x00050021
95461a98a2SAlexander Motin #define ASUS_WMI_DEVID_LIGHT_SENSOR 0x00050022
96461a98a2SAlexander Motin
97461a98a2SAlexander Motin /* Misc */
98461a98a2SAlexander Motin #define ASUS_WMI_DEVID_CAMERA 0x00060013
99461a98a2SAlexander Motin #define ASUS_WMI_DEVID_CARDREADER 0x00080013
100461a98a2SAlexander Motin #define ASUS_WMI_DEVID_TOUCHPAD 0x00100011
101461a98a2SAlexander Motin #define ASUS_WMI_DEVID_TOUCHPAD_LED 0x00100012
102*027b93c2SVladimir Kondratyev #define ASUS_WMI_DEVID_TUF_RGB_MODE 0x00100056
103461a98a2SAlexander Motin #define ASUS_WMI_DEVID_THERMAL_CTRL 0x00110011
104461a98a2SAlexander Motin #define ASUS_WMI_DEVID_FAN_CTRL 0x00110012
105461a98a2SAlexander Motin #define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012
106*027b93c2SVladimir Kondratyev #define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY 0x00120075
107461a98a2SAlexander Motin
108461a98a2SAlexander Motin /* DSTS masks */
109461a98a2SAlexander Motin #define ASUS_WMI_DSTS_STATUS_BIT 0x00000001
110461a98a2SAlexander Motin #define ASUS_WMI_DSTS_UNKNOWN_BIT 0x00000002
111461a98a2SAlexander Motin #define ASUS_WMI_DSTS_PRESENCE_BIT 0x00010000
112461a98a2SAlexander Motin #define ASUS_WMI_DSTS_USER_BIT 0x00020000
113461a98a2SAlexander Motin #define ASUS_WMI_DSTS_BIOS_BIT 0x00040000
114461a98a2SAlexander Motin #define ASUS_WMI_DSTS_BRIGHTNESS_MASK 0x000000FF
115461a98a2SAlexander Motin #define ASUS_WMI_DSTS_MAX_BRIGTH_MASK 0x0000FF00
116461a98a2SAlexander Motin
117d5bf6a72SVladimir Kondratyev /* Events */
118d5bf6a72SVladimir Kondratyev #define ASUS_WMI_EVENT_QUEUE_SIZE 0x10
119d5bf6a72SVladimir Kondratyev #define ASUS_WMI_EVENT_QUEUE_END 0x1
120d5bf6a72SVladimir Kondratyev #define ASUS_WMI_EVENT_MASK 0xFFFF
121d5bf6a72SVladimir Kondratyev #define ASUS_WMI_EVENT_VALUE_ATK 0xFF
122d5bf6a72SVladimir Kondratyev
123461a98a2SAlexander Motin struct acpi_asus_wmi_softc {
124461a98a2SAlexander Motin device_t dev;
125461a98a2SAlexander Motin device_t wmi_dev;
126461a98a2SAlexander Motin const char *notify_guid;
127461a98a2SAlexander Motin struct sysctl_ctx_list *sysctl_ctx;
128461a98a2SAlexander Motin struct sysctl_oid *sysctl_tree;
129461a98a2SAlexander Motin int dsts_id;
130461a98a2SAlexander Motin int handle_keys;
131d5bf6a72SVladimir Kondratyev bool event_queue;
132f134662aSVladimir Kondratyev struct cdev *kbd_bkl;
133f134662aSVladimir Kondratyev uint32_t kbd_bkl_level;
134*027b93c2SVladimir Kondratyev uint32_t tuf_rgb_mode;
135*027b93c2SVladimir Kondratyev uint32_t ttp_mode;
1365e41194bSVladimir Kondratyev #ifdef EVDEV_SUPPORT
1375e41194bSVladimir Kondratyev struct evdev_dev *evdev;
1385e41194bSVladimir Kondratyev #endif
139461a98a2SAlexander Motin };
140461a98a2SAlexander Motin
141461a98a2SAlexander Motin static struct {
142461a98a2SAlexander Motin char *name;
143461a98a2SAlexander Motin int dev_id;
144461a98a2SAlexander Motin char *description;
145f0188618SHans Petter Selasky int flag_rdonly;
146461a98a2SAlexander Motin } acpi_asus_wmi_sysctls[] = {
147461a98a2SAlexander Motin {
148461a98a2SAlexander Motin .name = "hw_switch",
149461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_HW_SWITCH,
150461a98a2SAlexander Motin .description = "hw_switch",
151461a98a2SAlexander Motin },
152461a98a2SAlexander Motin {
153461a98a2SAlexander Motin .name = "wireless_led",
154461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_WIRELESS_LED,
155461a98a2SAlexander Motin .description = "Wireless LED control",
156461a98a2SAlexander Motin },
157461a98a2SAlexander Motin {
158461a98a2SAlexander Motin .name = "cwap",
159461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_CWAP,
160461a98a2SAlexander Motin .description = "Alt+F2 function",
161461a98a2SAlexander Motin },
162461a98a2SAlexander Motin {
163461a98a2SAlexander Motin .name = "wlan",
164461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_WLAN,
165461a98a2SAlexander Motin .description = "WLAN power control",
166461a98a2SAlexander Motin },
167461a98a2SAlexander Motin {
168461a98a2SAlexander Motin .name = "bluetooth",
169461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_BLUETOOTH,
170461a98a2SAlexander Motin .description = "Bluetooth power control",
171461a98a2SAlexander Motin },
172461a98a2SAlexander Motin {
173461a98a2SAlexander Motin .name = "gps",
174461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_GPS,
175461a98a2SAlexander Motin .description = "GPS power control",
176461a98a2SAlexander Motin },
177461a98a2SAlexander Motin {
178461a98a2SAlexander Motin .name = "wimax",
179461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_WIMAX,
180461a98a2SAlexander Motin .description = "WiMAX power control",
181461a98a2SAlexander Motin },
182461a98a2SAlexander Motin {
183461a98a2SAlexander Motin .name = "wwan3g",
184461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_WWAN3G,
185461a98a2SAlexander Motin .description = "WWAN-3G power control",
186461a98a2SAlexander Motin },
187461a98a2SAlexander Motin {
188461a98a2SAlexander Motin .name = "uwb",
189461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_UWB,
190461a98a2SAlexander Motin .description = "UWB power control",
191461a98a2SAlexander Motin },
192461a98a2SAlexander Motin {
193461a98a2SAlexander Motin .name = "led1",
194461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_LED1,
195461a98a2SAlexander Motin .description = "LED1 control",
196461a98a2SAlexander Motin },
197461a98a2SAlexander Motin {
198461a98a2SAlexander Motin .name = "led2",
199461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_LED2,
200461a98a2SAlexander Motin .description = "LED2 control",
201461a98a2SAlexander Motin },
202461a98a2SAlexander Motin {
203461a98a2SAlexander Motin .name = "led3",
204461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_LED3,
205461a98a2SAlexander Motin .description = "LED3 control",
206461a98a2SAlexander Motin },
207461a98a2SAlexander Motin {
208461a98a2SAlexander Motin .name = "led4",
209461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_LED4,
210461a98a2SAlexander Motin .description = "LED4 control",
211461a98a2SAlexander Motin },
212461a98a2SAlexander Motin {
213461a98a2SAlexander Motin .name = "led5",
214461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_LED5,
215461a98a2SAlexander Motin .description = "LED5 control",
216461a98a2SAlexander Motin },
217461a98a2SAlexander Motin {
218461a98a2SAlexander Motin .name = "led6",
219461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_LED6,
220461a98a2SAlexander Motin .description = "LED6 control",
221461a98a2SAlexander Motin },
222461a98a2SAlexander Motin {
223461a98a2SAlexander Motin .name = "backlight",
224461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_BACKLIGHT,
225461a98a2SAlexander Motin .description = "LCD backlight on/off control",
226461a98a2SAlexander Motin },
227461a98a2SAlexander Motin {
228461a98a2SAlexander Motin .name = "brightness",
229461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_BRIGHTNESS,
230461a98a2SAlexander Motin .description = "LCD backlight brightness control",
231461a98a2SAlexander Motin },
232461a98a2SAlexander Motin {
233461a98a2SAlexander Motin .name = "kbd_backlight",
234461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_KBD_BACKLIGHT,
235461a98a2SAlexander Motin .description = "Keyboard backlight brightness control",
236461a98a2SAlexander Motin },
237461a98a2SAlexander Motin {
238461a98a2SAlexander Motin .name = "light_sensor",
239461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_LIGHT_SENSOR,
240461a98a2SAlexander Motin .description = "Ambient light sensor",
241461a98a2SAlexander Motin },
242461a98a2SAlexander Motin {
243461a98a2SAlexander Motin .name = "camera",
244461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_CAMERA,
245461a98a2SAlexander Motin .description = "Camera power control",
246461a98a2SAlexander Motin },
247461a98a2SAlexander Motin {
248461a98a2SAlexander Motin .name = "cardreader",
249461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_CARDREADER,
250461a98a2SAlexander Motin .description = "Cardreader power control",
251461a98a2SAlexander Motin },
252461a98a2SAlexander Motin {
253461a98a2SAlexander Motin .name = "touchpad",
254461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_TOUCHPAD,
255461a98a2SAlexander Motin .description = "Touchpad control",
256461a98a2SAlexander Motin },
257461a98a2SAlexander Motin {
258461a98a2SAlexander Motin .name = "touchpad_led",
259461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_TOUCHPAD_LED,
260461a98a2SAlexander Motin .description = "Touchpad LED control",
261461a98a2SAlexander Motin },
262461a98a2SAlexander Motin {
263461a98a2SAlexander Motin .name = "themperature",
264461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_THERMAL_CTRL,
265461a98a2SAlexander Motin .description = "Temperature (C)",
266f0188618SHans Petter Selasky .flag_rdonly = 1
267461a98a2SAlexander Motin },
268461a98a2SAlexander Motin {
269461a98a2SAlexander Motin .name = "fan_speed",
270461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_FAN_CTRL,
271461a98a2SAlexander Motin .description = "Fan speed (0-3)",
272f0188618SHans Petter Selasky .flag_rdonly = 1
273461a98a2SAlexander Motin },
274461a98a2SAlexander Motin {
275461a98a2SAlexander Motin .name = "processor_state",
276461a98a2SAlexander Motin .dev_id = ASUS_WMI_DEVID_PROCESSOR_STATE,
277f0188618SHans Petter Selasky .flag_rdonly = 1
278461a98a2SAlexander Motin },
279*027b93c2SVladimir Kondratyev {
280*027b93c2SVladimir Kondratyev .name = "throttle_thermal_policy",
281*027b93c2SVladimir Kondratyev .dev_id = ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY,
282*027b93c2SVladimir Kondratyev .description = "Throttle Thermal Policy "
283*027b93c2SVladimir Kondratyev "(0 - default, 1 - overboost, 2 - silent)",
284*027b93c2SVladimir Kondratyev },
285461a98a2SAlexander Motin { NULL, 0, NULL, 0 }
286461a98a2SAlexander Motin };
287461a98a2SAlexander Motin
2885e41194bSVladimir Kondratyev #ifdef EVDEV_SUPPORT
2895e41194bSVladimir Kondratyev static const struct {
2905e41194bSVladimir Kondratyev UINT32 notify;
2915e41194bSVladimir Kondratyev uint16_t key;
2925e41194bSVladimir Kondratyev } acpi_asus_wmi_evdev_map[] = {
2935e41194bSVladimir Kondratyev { 0x20, KEY_BRIGHTNESSDOWN },
2945e41194bSVladimir Kondratyev { 0x2f, KEY_BRIGHTNESSUP },
2955e41194bSVladimir Kondratyev { 0x30, KEY_VOLUMEUP },
2965e41194bSVladimir Kondratyev { 0x31, KEY_VOLUMEDOWN },
2975e41194bSVladimir Kondratyev { 0x32, KEY_MUTE },
2985e41194bSVladimir Kondratyev { 0x35, KEY_SCREENLOCK },
2995e41194bSVladimir Kondratyev { 0x38, KEY_PROG3 }, /* Armoury Crate */
3005e41194bSVladimir Kondratyev { 0x40, KEY_PREVIOUSSONG },
3015e41194bSVladimir Kondratyev { 0x41, KEY_NEXTSONG },
3025e41194bSVladimir Kondratyev { 0x43, KEY_STOPCD }, /* Stop/Eject */
3035e41194bSVladimir Kondratyev { 0x45, KEY_PLAYPAUSE },
3045e41194bSVladimir Kondratyev { 0x4f, KEY_LEFTMETA }, /* Fn-locked "Windows" Key */
3055e41194bSVladimir Kondratyev { 0x4c, KEY_MEDIA }, /* WMP Key */
3065e41194bSVladimir Kondratyev { 0x50, KEY_EMAIL },
3075e41194bSVladimir Kondratyev { 0x51, KEY_WWW },
3085e41194bSVladimir Kondratyev { 0x55, KEY_CALC },
3095e41194bSVladimir Kondratyev { 0x57, NO_KEY }, /* Battery mode */
3105e41194bSVladimir Kondratyev { 0x58, NO_KEY }, /* AC mode */
3115e41194bSVladimir Kondratyev { 0x5C, KEY_F15 }, /* Power Gear key */
3125e41194bSVladimir Kondratyev { 0x5D, KEY_WLAN }, /* Wireless console Toggle */
3135e41194bSVladimir Kondratyev { 0x5E, KEY_WLAN }, /* Wireless console Enable */
3145e41194bSVladimir Kondratyev { 0x5F, KEY_WLAN }, /* Wireless console Disable */
3155e41194bSVladimir Kondratyev { 0x60, KEY_TOUCHPAD_ON },
3165e41194bSVladimir Kondratyev { 0x61, KEY_SWITCHVIDEOMODE }, /* SDSP LCD only */
3175e41194bSVladimir Kondratyev { 0x62, KEY_SWITCHVIDEOMODE }, /* SDSP CRT only */
3185e41194bSVladimir Kondratyev { 0x63, KEY_SWITCHVIDEOMODE }, /* SDSP LCD + CRT */
3195e41194bSVladimir Kondratyev { 0x64, KEY_SWITCHVIDEOMODE }, /* SDSP TV */
3205e41194bSVladimir Kondratyev { 0x65, KEY_SWITCHVIDEOMODE }, /* SDSP LCD + TV */
3215e41194bSVladimir Kondratyev { 0x66, KEY_SWITCHVIDEOMODE }, /* SDSP CRT + TV */
3225e41194bSVladimir Kondratyev { 0x67, KEY_SWITCHVIDEOMODE }, /* SDSP LCD + CRT + TV */
3235e41194bSVladimir Kondratyev { 0x6B, KEY_TOUCHPAD_TOGGLE },
3245e41194bSVladimir Kondratyev { 0x6E, NO_KEY }, /* Low Battery notification */
3255e41194bSVladimir Kondratyev { 0x71, KEY_F13 }, /* General-purpose button */
3265e41194bSVladimir Kondratyev { 0x79, NO_KEY }, /* Charger type dectection notification */
3275e41194bSVladimir Kondratyev { 0x7a, KEY_ALS_TOGGLE }, /* Ambient Light Sensor Toggle */
3285e41194bSVladimir Kondratyev { 0x7c, KEY_MICMUTE },
3295e41194bSVladimir Kondratyev { 0x7D, KEY_BLUETOOTH }, /* Bluetooth Enable */
3305e41194bSVladimir Kondratyev { 0x7E, KEY_BLUETOOTH }, /* Bluetooth Disable */
3315e41194bSVladimir Kondratyev { 0x82, KEY_CAMERA },
3325e41194bSVladimir Kondratyev { 0x86, KEY_PROG1 }, /* MyASUS Key */
3335e41194bSVladimir Kondratyev { 0x88, KEY_RFKILL }, /* Radio Toggle Key */
3345e41194bSVladimir Kondratyev { 0x8A, KEY_PROG1 }, /* Color enhancement mode */
3355e41194bSVladimir Kondratyev { 0x8C, KEY_SWITCHVIDEOMODE }, /* SDSP DVI only */
3365e41194bSVladimir Kondratyev { 0x8D, KEY_SWITCHVIDEOMODE }, /* SDSP LCD + DVI */
3375e41194bSVladimir Kondratyev { 0x8E, KEY_SWITCHVIDEOMODE }, /* SDSP CRT + DVI */
3385e41194bSVladimir Kondratyev { 0x8F, KEY_SWITCHVIDEOMODE }, /* SDSP TV + DVI */
3395e41194bSVladimir Kondratyev { 0x90, KEY_SWITCHVIDEOMODE }, /* SDSP LCD + CRT + DVI */
3405e41194bSVladimir Kondratyev { 0x91, KEY_SWITCHVIDEOMODE }, /* SDSP LCD + TV + DVI */
3415e41194bSVladimir Kondratyev { 0x92, KEY_SWITCHVIDEOMODE }, /* SDSP CRT + TV + DVI */
3425e41194bSVladimir Kondratyev { 0x93, KEY_SWITCHVIDEOMODE }, /* SDSP LCD + CRT + TV + DVI */
3435e41194bSVladimir Kondratyev { 0x95, KEY_MEDIA },
3445e41194bSVladimir Kondratyev { 0x99, KEY_PHONE }, /* Conflicts with fan mode switch */
3455e41194bSVladimir Kondratyev { 0xA0, KEY_SWITCHVIDEOMODE }, /* SDSP HDMI only */
3465e41194bSVladimir Kondratyev { 0xA1, KEY_SWITCHVIDEOMODE }, /* SDSP LCD + HDMI */
3475e41194bSVladimir Kondratyev { 0xA2, KEY_SWITCHVIDEOMODE }, /* SDSP CRT + HDMI */
3485e41194bSVladimir Kondratyev { 0xA3, KEY_SWITCHVIDEOMODE }, /* SDSP TV + HDMI */
3495e41194bSVladimir Kondratyev { 0xA4, KEY_SWITCHVIDEOMODE }, /* SDSP LCD + CRT + HDMI */
3505e41194bSVladimir Kondratyev { 0xA5, KEY_SWITCHVIDEOMODE }, /* SDSP LCD + TV + HDMI */
3515e41194bSVladimir Kondratyev { 0xA6, KEY_SWITCHVIDEOMODE }, /* SDSP CRT + TV + HDMI */
3525e41194bSVladimir Kondratyev { 0xA7, KEY_SWITCHVIDEOMODE }, /* SDSP LCD + CRT + TV + HDMI */
3535e41194bSVladimir Kondratyev { 0xAE, KEY_FN_F5 }, /* Fn+F5 fan mode on 2020+ */
3545e41194bSVladimir Kondratyev { 0xB3, KEY_PROG4 }, /* AURA */
3555e41194bSVladimir Kondratyev { 0xB5, KEY_CALC },
3565e41194bSVladimir Kondratyev { 0xC4, KEY_KBDILLUMUP },
3575e41194bSVladimir Kondratyev { 0xC5, KEY_KBDILLUMDOWN },
3585e41194bSVladimir Kondratyev { 0xC6, NO_KEY }, /* Ambient Light Sensor notification */
3595e41194bSVladimir Kondratyev { 0xFA, KEY_PROG2 }, /* Lid flip action */
3605e41194bSVladimir Kondratyev { 0xBD, KEY_PROG2 }, /* Lid flip action on ROG xflow laptops */
3615e41194bSVladimir Kondratyev };
3625e41194bSVladimir Kondratyev #endif
3635e41194bSVladimir Kondratyev
364461a98a2SAlexander Motin ACPI_SERIAL_DECL(asus_wmi, "ASUS WMI device");
365461a98a2SAlexander Motin
366461a98a2SAlexander Motin static void acpi_asus_wmi_identify(driver_t *driver, device_t parent);
367461a98a2SAlexander Motin static int acpi_asus_wmi_probe(device_t dev);
368461a98a2SAlexander Motin static int acpi_asus_wmi_attach(device_t dev);
369461a98a2SAlexander Motin static int acpi_asus_wmi_detach(device_t dev);
370f134662aSVladimir Kondratyev static int acpi_asus_wmi_suspend(device_t dev);
371f134662aSVladimir Kondratyev static int acpi_asus_wmi_resume(device_t dev);
372461a98a2SAlexander Motin
373461a98a2SAlexander Motin static int acpi_asus_wmi_sysctl(SYSCTL_HANDLER_ARGS);
374461a98a2SAlexander Motin static int acpi_asus_wmi_sysctl_set(struct acpi_asus_wmi_softc *sc, int dev_id,
375461a98a2SAlexander Motin int arg, int oldarg);
376461a98a2SAlexander Motin static int acpi_asus_wmi_sysctl_get(struct acpi_asus_wmi_softc *sc, int dev_id);
377461a98a2SAlexander Motin static int acpi_asus_wmi_evaluate_method(device_t wmi_dev, int method,
378*027b93c2SVladimir Kondratyev UINT32 arg0, UINT32 arg1, UINT32 arg2, UINT32 *retval);
379461a98a2SAlexander Motin static int acpi_wpi_asus_get_devstate(struct acpi_asus_wmi_softc *sc,
380461a98a2SAlexander Motin UINT32 dev_id, UINT32 *retval);
381461a98a2SAlexander Motin static int acpi_wpi_asus_set_devstate(struct acpi_asus_wmi_softc *sc,
382461a98a2SAlexander Motin UINT32 dev_id, UINT32 ctrl_param, UINT32 *retval);
383d5bf6a72SVladimir Kondratyev static int acpi_asus_wmi_get_event_code(device_t wmi_dev, UINT32 notify,
384d5bf6a72SVladimir Kondratyev int *code);
385461a98a2SAlexander Motin static void acpi_asus_wmi_notify(ACPI_HANDLE h, UINT32 notify, void *context);
386f134662aSVladimir Kondratyev static int acpi_asus_wmi_backlight_update_status(device_t dev,
387f134662aSVladimir Kondratyev struct backlight_props *props);
388f134662aSVladimir Kondratyev static int acpi_asus_wmi_backlight_get_status(device_t dev,
389f134662aSVladimir Kondratyev struct backlight_props *props);
390f134662aSVladimir Kondratyev static int acpi_asus_wmi_backlight_get_info(device_t dev,
391f134662aSVladimir Kondratyev struct backlight_info *info);
392461a98a2SAlexander Motin
393461a98a2SAlexander Motin static device_method_t acpi_asus_wmi_methods[] = {
394f134662aSVladimir Kondratyev /* Device interface */
395461a98a2SAlexander Motin DEVMETHOD(device_identify, acpi_asus_wmi_identify),
396461a98a2SAlexander Motin DEVMETHOD(device_probe, acpi_asus_wmi_probe),
397461a98a2SAlexander Motin DEVMETHOD(device_attach, acpi_asus_wmi_attach),
398461a98a2SAlexander Motin DEVMETHOD(device_detach, acpi_asus_wmi_detach),
399f134662aSVladimir Kondratyev DEVMETHOD(device_suspend, acpi_asus_wmi_suspend),
400f134662aSVladimir Kondratyev DEVMETHOD(device_resume, acpi_asus_wmi_resume),
401f134662aSVladimir Kondratyev
402f134662aSVladimir Kondratyev /* Backlight interface */
403f134662aSVladimir Kondratyev DEVMETHOD(backlight_update_status, acpi_asus_wmi_backlight_update_status),
404f134662aSVladimir Kondratyev DEVMETHOD(backlight_get_status, acpi_asus_wmi_backlight_get_status),
405f134662aSVladimir Kondratyev DEVMETHOD(backlight_get_info, acpi_asus_wmi_backlight_get_info),
40661bfd867SSofian Brabez
40761bfd867SSofian Brabez DEVMETHOD_END
408461a98a2SAlexander Motin };
409461a98a2SAlexander Motin
410461a98a2SAlexander Motin static driver_t acpi_asus_wmi_driver = {
411461a98a2SAlexander Motin "acpi_asus_wmi",
412461a98a2SAlexander Motin acpi_asus_wmi_methods,
413461a98a2SAlexander Motin sizeof(struct acpi_asus_wmi_softc),
414461a98a2SAlexander Motin };
415461a98a2SAlexander Motin
41690161e72SJohn Baldwin DRIVER_MODULE(acpi_asus_wmi, acpi_wmi, acpi_asus_wmi_driver, 0, 0);
417461a98a2SAlexander Motin MODULE_DEPEND(acpi_asus_wmi, acpi_wmi, 1, 1, 1);
418461a98a2SAlexander Motin MODULE_DEPEND(acpi_asus_wmi, acpi, 1, 1, 1);
419f134662aSVladimir Kondratyev MODULE_DEPEND(acpi_asus_wmi, backlight, 1, 1, 1);
4205e41194bSVladimir Kondratyev #ifdef EVDEV_SUPPORT
4215e41194bSVladimir Kondratyev MODULE_DEPEND(acpi_asus_wmi, evdev, 1, 1, 1);
4225e41194bSVladimir Kondratyev #endif
423461a98a2SAlexander Motin
424f134662aSVladimir Kondratyev static const uint32_t acpi_asus_wmi_backlight_levels[] = { 0, 33, 66, 100 };
425f134662aSVladimir Kondratyev
426f134662aSVladimir Kondratyev static inline uint32_t
devstate_to_kbd_bkl_level(UINT32 val)427f134662aSVladimir Kondratyev devstate_to_kbd_bkl_level(UINT32 val)
428f134662aSVladimir Kondratyev {
429f134662aSVladimir Kondratyev return (acpi_asus_wmi_backlight_levels[val & 0x3]);
430f134662aSVladimir Kondratyev }
431f134662aSVladimir Kondratyev
432f134662aSVladimir Kondratyev static inline UINT32
kbd_bkl_level_to_devstate(uint32_t bkl)433f134662aSVladimir Kondratyev kbd_bkl_level_to_devstate(uint32_t bkl)
434f134662aSVladimir Kondratyev {
435f134662aSVladimir Kondratyev UINT32 val;
436f134662aSVladimir Kondratyev int i;
437f134662aSVladimir Kondratyev
438f134662aSVladimir Kondratyev for (i = 0; i < nitems(acpi_asus_wmi_backlight_levels); i++) {
439f134662aSVladimir Kondratyev if (bkl < acpi_asus_wmi_backlight_levels[i])
440f134662aSVladimir Kondratyev break;
441f134662aSVladimir Kondratyev }
442f134662aSVladimir Kondratyev val = (i - 1) & 0x3;
443f134662aSVladimir Kondratyev if (val != 0)
444f134662aSVladimir Kondratyev val |= 0x80;
445f134662aSVladimir Kondratyev return(val);
446f134662aSVladimir Kondratyev }
447f134662aSVladimir Kondratyev
448461a98a2SAlexander Motin static void
acpi_asus_wmi_identify(driver_t * driver,device_t parent)449461a98a2SAlexander Motin acpi_asus_wmi_identify(driver_t *driver, device_t parent)
450461a98a2SAlexander Motin {
451461a98a2SAlexander Motin
452461a98a2SAlexander Motin /* Don't do anything if driver is disabled. */
453461a98a2SAlexander Motin if (acpi_disabled("asus_wmi"))
454461a98a2SAlexander Motin return;
455461a98a2SAlexander Motin
456461a98a2SAlexander Motin /* Add only a single device instance. */
457461a98a2SAlexander Motin if (device_find_child(parent, "acpi_asus_wmi", -1) != NULL)
458461a98a2SAlexander Motin return;
459461a98a2SAlexander Motin
460461a98a2SAlexander Motin /* Check management GUID to see whether system is compatible. */
461461a98a2SAlexander Motin if (!ACPI_WMI_PROVIDES_GUID_STRING(parent,
462461a98a2SAlexander Motin ACPI_ASUS_WMI_MGMT_GUID))
463461a98a2SAlexander Motin return;
464461a98a2SAlexander Motin
465461a98a2SAlexander Motin if (BUS_ADD_CHILD(parent, 0, "acpi_asus_wmi", -1) == NULL)
466461a98a2SAlexander Motin device_printf(parent, "add acpi_asus_wmi child failed\n");
467461a98a2SAlexander Motin }
468461a98a2SAlexander Motin
469461a98a2SAlexander Motin static int
acpi_asus_wmi_probe(device_t dev)470461a98a2SAlexander Motin acpi_asus_wmi_probe(device_t dev)
471461a98a2SAlexander Motin {
472461a98a2SAlexander Motin
473461a98a2SAlexander Motin if (!ACPI_WMI_PROVIDES_GUID_STRING(device_get_parent(dev),
474461a98a2SAlexander Motin ACPI_ASUS_WMI_MGMT_GUID))
475461a98a2SAlexander Motin return (EINVAL);
476461a98a2SAlexander Motin device_set_desc(dev, "ASUS WMI device");
477461a98a2SAlexander Motin return (0);
478461a98a2SAlexander Motin }
479461a98a2SAlexander Motin
480461a98a2SAlexander Motin static int
acpi_asus_wmi_attach(device_t dev)481461a98a2SAlexander Motin acpi_asus_wmi_attach(device_t dev)
482461a98a2SAlexander Motin {
483461a98a2SAlexander Motin struct acpi_asus_wmi_softc *sc;
484461a98a2SAlexander Motin UINT32 val;
485d5bf6a72SVladimir Kondratyev int dev_id, i, code;
486f134662aSVladimir Kondratyev bool have_kbd_bkl = false;
487461a98a2SAlexander Motin
488461a98a2SAlexander Motin ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
489461a98a2SAlexander Motin
490461a98a2SAlexander Motin sc = device_get_softc(dev);
491461a98a2SAlexander Motin sc->dev = dev;
492461a98a2SAlexander Motin sc->wmi_dev = device_get_parent(dev);
493461a98a2SAlexander Motin sc->handle_keys = 1;
494461a98a2SAlexander Motin
495461a98a2SAlexander Motin /* Check management GUID. */
496461a98a2SAlexander Motin if (!ACPI_WMI_PROVIDES_GUID_STRING(sc->wmi_dev,
497461a98a2SAlexander Motin ACPI_ASUS_WMI_MGMT_GUID)) {
498461a98a2SAlexander Motin device_printf(dev,
499461a98a2SAlexander Motin "WMI device does not provide the ASUS management GUID\n");
500461a98a2SAlexander Motin return (EINVAL);
501461a98a2SAlexander Motin }
502461a98a2SAlexander Motin
503461a98a2SAlexander Motin /* Find proper DSTS method. */
504461a98a2SAlexander Motin sc->dsts_id = ASUS_WMI_METHODID_DSTS;
505461a98a2SAlexander Motin next:
506461a98a2SAlexander Motin for (i = 0; acpi_asus_wmi_sysctls[i].name != NULL; ++i) {
507461a98a2SAlexander Motin dev_id = acpi_asus_wmi_sysctls[i].dev_id;
508461a98a2SAlexander Motin if (acpi_wpi_asus_get_devstate(sc, dev_id, &val))
509461a98a2SAlexander Motin continue;
510461a98a2SAlexander Motin break;
511461a98a2SAlexander Motin }
512461a98a2SAlexander Motin if (acpi_asus_wmi_sysctls[i].name == NULL) {
513461a98a2SAlexander Motin if (sc->dsts_id == ASUS_WMI_METHODID_DSTS) {
514461a98a2SAlexander Motin sc->dsts_id = ASUS_WMI_METHODID_DSTS2;
515461a98a2SAlexander Motin goto next;
516461a98a2SAlexander Motin } else {
517461a98a2SAlexander Motin device_printf(dev, "Can not detect DSTS method ID\n");
518461a98a2SAlexander Motin return (EINVAL);
519461a98a2SAlexander Motin }
520461a98a2SAlexander Motin }
521461a98a2SAlexander Motin
522461a98a2SAlexander Motin /* Find proper and attach to notufy GUID. */
523461a98a2SAlexander Motin if (ACPI_WMI_PROVIDES_GUID_STRING(sc->wmi_dev,
524461a98a2SAlexander Motin ACPI_ASUS_WMI_EVENT_GUID))
525461a98a2SAlexander Motin sc->notify_guid = ACPI_ASUS_WMI_EVENT_GUID;
526461a98a2SAlexander Motin else if (ACPI_WMI_PROVIDES_GUID_STRING(sc->wmi_dev,
527461a98a2SAlexander Motin ACPI_EEEPC_WMI_EVENT_GUID))
528461a98a2SAlexander Motin sc->notify_guid = ACPI_EEEPC_WMI_EVENT_GUID;
529461a98a2SAlexander Motin else
530461a98a2SAlexander Motin sc->notify_guid = NULL;
531461a98a2SAlexander Motin if (sc->notify_guid != NULL) {
532461a98a2SAlexander Motin if (ACPI_WMI_INSTALL_EVENT_HANDLER(sc->wmi_dev,
533461a98a2SAlexander Motin sc->notify_guid, acpi_asus_wmi_notify, dev))
534461a98a2SAlexander Motin sc->notify_guid = NULL;
535461a98a2SAlexander Motin }
536461a98a2SAlexander Motin if (sc->notify_guid == NULL)
537461a98a2SAlexander Motin device_printf(dev, "Could not install event handler!\n");
538461a98a2SAlexander Motin
539461a98a2SAlexander Motin /* Initialize. */
540461a98a2SAlexander Motin if (!acpi_asus_wmi_evaluate_method(sc->wmi_dev,
541*027b93c2SVladimir Kondratyev ASUS_WMI_METHODID_INIT, 0, 0, 0, &val) && bootverbose)
542461a98a2SAlexander Motin device_printf(dev, "Initialization: %#x\n", val);
543461a98a2SAlexander Motin if (!acpi_asus_wmi_evaluate_method(sc->wmi_dev,
544*027b93c2SVladimir Kondratyev ASUS_WMI_METHODID_SPEC, 0, 0x9, 0, &val) && bootverbose)
545461a98a2SAlexander Motin device_printf(dev, "WMI BIOS version: %d.%d\n",
546461a98a2SAlexander Motin val >> 16, val & 0xFF);
547461a98a2SAlexander Motin if (!acpi_asus_wmi_evaluate_method(sc->wmi_dev,
548*027b93c2SVladimir Kondratyev ASUS_WMI_METHODID_SFUN, 0, 0, 0, &val) && bootverbose)
549461a98a2SAlexander Motin device_printf(dev, "SFUN value: %#x\n", val);
550461a98a2SAlexander Motin
551461a98a2SAlexander Motin ACPI_SERIAL_BEGIN(asus_wmi);
552461a98a2SAlexander Motin
553461a98a2SAlexander Motin sc->sysctl_ctx = device_get_sysctl_ctx(dev);
554461a98a2SAlexander Motin sc->sysctl_tree = device_get_sysctl_tree(dev);
555461a98a2SAlexander Motin SYSCTL_ADD_INT(sc->sysctl_ctx,
556461a98a2SAlexander Motin SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO,
557461a98a2SAlexander Motin "handle_keys", CTLFLAG_RW, &sc->handle_keys,
558461a98a2SAlexander Motin 0, "Handle some hardware keys inside the driver");
559461a98a2SAlexander Motin for (i = 0; acpi_asus_wmi_sysctls[i].name != NULL; ++i) {
560461a98a2SAlexander Motin dev_id = acpi_asus_wmi_sysctls[i].dev_id;
561461a98a2SAlexander Motin if (acpi_wpi_asus_get_devstate(sc, dev_id, &val))
562461a98a2SAlexander Motin continue;
563461a98a2SAlexander Motin switch (dev_id) {
564461a98a2SAlexander Motin case ASUS_WMI_DEVID_THERMAL_CTRL:
565461a98a2SAlexander Motin case ASUS_WMI_DEVID_PROCESSOR_STATE:
566461a98a2SAlexander Motin case ASUS_WMI_DEVID_FAN_CTRL:
567461a98a2SAlexander Motin case ASUS_WMI_DEVID_BRIGHTNESS:
568461a98a2SAlexander Motin if (val == 0)
569461a98a2SAlexander Motin continue;
570461a98a2SAlexander Motin break;
571f134662aSVladimir Kondratyev case ASUS_WMI_DEVID_KBD_BACKLIGHT:
572f134662aSVladimir Kondratyev sc->kbd_bkl_level = devstate_to_kbd_bkl_level(val);
573f134662aSVladimir Kondratyev have_kbd_bkl = true;
574f134662aSVladimir Kondratyev /* FALLTHROUGH */
575461a98a2SAlexander Motin default:
576461a98a2SAlexander Motin if ((val & ASUS_WMI_DSTS_PRESENCE_BIT) == 0)
577461a98a2SAlexander Motin continue;
578461a98a2SAlexander Motin break;
579461a98a2SAlexander Motin }
580461a98a2SAlexander Motin
581f0188618SHans Petter Selasky if (acpi_asus_wmi_sysctls[i].flag_rdonly != 0) {
582461a98a2SAlexander Motin SYSCTL_ADD_PROC(sc->sysctl_ctx,
583461a98a2SAlexander Motin SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO,
584461a98a2SAlexander Motin acpi_asus_wmi_sysctls[i].name,
5856237a1ccSAlexander Motin CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
586461a98a2SAlexander Motin sc, i, acpi_asus_wmi_sysctl, "I",
587461a98a2SAlexander Motin acpi_asus_wmi_sysctls[i].description);
588f0188618SHans Petter Selasky } else {
589f0188618SHans Petter Selasky SYSCTL_ADD_PROC(sc->sysctl_ctx,
590f0188618SHans Petter Selasky SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO,
591f0188618SHans Petter Selasky acpi_asus_wmi_sysctls[i].name,
5926237a1ccSAlexander Motin CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
593f0188618SHans Petter Selasky sc, i, acpi_asus_wmi_sysctl, "I",
594f0188618SHans Petter Selasky acpi_asus_wmi_sysctls[i].description);
595f0188618SHans Petter Selasky }
596461a98a2SAlexander Motin }
597461a98a2SAlexander Motin ACPI_SERIAL_END(asus_wmi);
598461a98a2SAlexander Motin
599d5bf6a72SVladimir Kondratyev /* Detect and flush event queue */
600d5bf6a72SVladimir Kondratyev if (sc->dsts_id == ASUS_WMI_METHODID_DSTS2) {
601d5bf6a72SVladimir Kondratyev for (i = 0; i <= ASUS_WMI_EVENT_QUEUE_SIZE; i++) {
602d5bf6a72SVladimir Kondratyev if (acpi_asus_wmi_get_event_code(sc->wmi_dev,
603d5bf6a72SVladimir Kondratyev ASUS_WMI_EVENT_VALUE_ATK, &code) != 0) {
604d5bf6a72SVladimir Kondratyev device_printf(dev,
605d5bf6a72SVladimir Kondratyev "Can not flush event queue\n");
606d5bf6a72SVladimir Kondratyev break;
607d5bf6a72SVladimir Kondratyev }
608d5bf6a72SVladimir Kondratyev if (code == ASUS_WMI_EVENT_QUEUE_END ||
609d5bf6a72SVladimir Kondratyev code == ASUS_WMI_EVENT_MASK) {
610d5bf6a72SVladimir Kondratyev sc->event_queue = true;
611d5bf6a72SVladimir Kondratyev break;
612d5bf6a72SVladimir Kondratyev }
613d5bf6a72SVladimir Kondratyev }
614d5bf6a72SVladimir Kondratyev }
615d5bf6a72SVladimir Kondratyev
6165e41194bSVladimir Kondratyev #ifdef EVDEV_SUPPORT
6175e41194bSVladimir Kondratyev if (sc->notify_guid != NULL) {
6185e41194bSVladimir Kondratyev sc->evdev = evdev_alloc();
6195e41194bSVladimir Kondratyev evdev_set_name(sc->evdev, device_get_desc(dev));
6205e41194bSVladimir Kondratyev evdev_set_phys(sc->evdev, device_get_nameunit(dev));
6215e41194bSVladimir Kondratyev evdev_set_id(sc->evdev, BUS_HOST, 0, 0, 1);
6225e41194bSVladimir Kondratyev evdev_support_event(sc->evdev, EV_SYN);
6235e41194bSVladimir Kondratyev evdev_support_event(sc->evdev, EV_KEY);
6245e41194bSVladimir Kondratyev for (i = 0; i < nitems(acpi_asus_wmi_evdev_map); i++) {
6255e41194bSVladimir Kondratyev if (acpi_asus_wmi_evdev_map[i].key != NO_KEY)
6265e41194bSVladimir Kondratyev evdev_support_key(sc->evdev,
6275e41194bSVladimir Kondratyev acpi_asus_wmi_evdev_map[i].key);
6285e41194bSVladimir Kondratyev }
6295e41194bSVladimir Kondratyev
6305e41194bSVladimir Kondratyev if (evdev_register(sc->evdev) != 0) {
631f134662aSVladimir Kondratyev device_printf(dev, "Can not register evdev\n");
6325e41194bSVladimir Kondratyev acpi_asus_wmi_detach(dev);
6335e41194bSVladimir Kondratyev return (ENXIO);
6345e41194bSVladimir Kondratyev }
6355e41194bSVladimir Kondratyev }
6365e41194bSVladimir Kondratyev #endif
6375e41194bSVladimir Kondratyev
638f134662aSVladimir Kondratyev if (have_kbd_bkl) {
639f134662aSVladimir Kondratyev sc->kbd_bkl = backlight_register("acpi_asus_wmi", dev);
640f134662aSVladimir Kondratyev if (sc->kbd_bkl == NULL) {
641f134662aSVladimir Kondratyev device_printf(dev, "Can not register backlight\n");
642f134662aSVladimir Kondratyev acpi_asus_wmi_detach(dev);
643f134662aSVladimir Kondratyev return (ENXIO);
644f134662aSVladimir Kondratyev }
645f134662aSVladimir Kondratyev }
646f134662aSVladimir Kondratyev
647461a98a2SAlexander Motin return (0);
648461a98a2SAlexander Motin }
649461a98a2SAlexander Motin
650461a98a2SAlexander Motin static int
acpi_asus_wmi_detach(device_t dev)651461a98a2SAlexander Motin acpi_asus_wmi_detach(device_t dev)
652461a98a2SAlexander Motin {
653461a98a2SAlexander Motin struct acpi_asus_wmi_softc *sc = device_get_softc(dev);
654461a98a2SAlexander Motin
655461a98a2SAlexander Motin ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
656461a98a2SAlexander Motin
657f134662aSVladimir Kondratyev if (sc->kbd_bkl != NULL)
658f134662aSVladimir Kondratyev backlight_destroy(sc->kbd_bkl);
659f134662aSVladimir Kondratyev
6605e41194bSVladimir Kondratyev if (sc->notify_guid) {
661461a98a2SAlexander Motin ACPI_WMI_REMOVE_EVENT_HANDLER(dev, sc->notify_guid);
6625e41194bSVladimir Kondratyev #ifdef EVDEV_SUPPORT
6635e41194bSVladimir Kondratyev evdev_free(sc->evdev);
6645e41194bSVladimir Kondratyev #endif
6655e41194bSVladimir Kondratyev }
666461a98a2SAlexander Motin
667461a98a2SAlexander Motin return (0);
668461a98a2SAlexander Motin }
669461a98a2SAlexander Motin
670461a98a2SAlexander Motin static int
acpi_asus_wmi_suspend(device_t dev)671f134662aSVladimir Kondratyev acpi_asus_wmi_suspend(device_t dev)
672f134662aSVladimir Kondratyev {
673f134662aSVladimir Kondratyev struct acpi_asus_wmi_softc *sc = device_get_softc(dev);
674f134662aSVladimir Kondratyev
675f134662aSVladimir Kondratyev if (sc->kbd_bkl != NULL) {
676f134662aSVladimir Kondratyev ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
677f134662aSVladimir Kondratyev acpi_wpi_asus_set_devstate(sc,
678f134662aSVladimir Kondratyev ASUS_WMI_DEVID_KBD_BACKLIGHT, 0, NULL);
679f134662aSVladimir Kondratyev }
680f134662aSVladimir Kondratyev
681f134662aSVladimir Kondratyev return (0);
682f134662aSVladimir Kondratyev }
683f134662aSVladimir Kondratyev
684f134662aSVladimir Kondratyev static int
acpi_asus_wmi_resume(device_t dev)685f134662aSVladimir Kondratyev acpi_asus_wmi_resume(device_t dev)
686f134662aSVladimir Kondratyev {
687f134662aSVladimir Kondratyev struct acpi_asus_wmi_softc *sc = device_get_softc(dev);
688f134662aSVladimir Kondratyev
689f134662aSVladimir Kondratyev if (sc->kbd_bkl != NULL) {
690f134662aSVladimir Kondratyev ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
691f134662aSVladimir Kondratyev acpi_wpi_asus_set_devstate(sc, ASUS_WMI_DEVID_KBD_BACKLIGHT,
692f134662aSVladimir Kondratyev kbd_bkl_level_to_devstate(sc->kbd_bkl_level), NULL);
693f134662aSVladimir Kondratyev }
694f134662aSVladimir Kondratyev
695f134662aSVladimir Kondratyev return (0);
696f134662aSVladimir Kondratyev }
697f134662aSVladimir Kondratyev
698f134662aSVladimir Kondratyev static int
acpi_asus_wmi_sysctl(SYSCTL_HANDLER_ARGS)699461a98a2SAlexander Motin acpi_asus_wmi_sysctl(SYSCTL_HANDLER_ARGS)
700461a98a2SAlexander Motin {
701461a98a2SAlexander Motin struct acpi_asus_wmi_softc *sc;
702461a98a2SAlexander Motin int arg;
703461a98a2SAlexander Motin int oldarg;
704461a98a2SAlexander Motin int error = 0;
705461a98a2SAlexander Motin int function;
706461a98a2SAlexander Motin int dev_id;
707461a98a2SAlexander Motin
708461a98a2SAlexander Motin ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
709461a98a2SAlexander Motin
710461a98a2SAlexander Motin sc = (struct acpi_asus_wmi_softc *)oidp->oid_arg1;
711461a98a2SAlexander Motin function = oidp->oid_arg2;
712461a98a2SAlexander Motin dev_id = acpi_asus_wmi_sysctls[function].dev_id;
713461a98a2SAlexander Motin
714461a98a2SAlexander Motin ACPI_SERIAL_BEGIN(asus_wmi);
715461a98a2SAlexander Motin arg = acpi_asus_wmi_sysctl_get(sc, dev_id);
716461a98a2SAlexander Motin oldarg = arg;
717461a98a2SAlexander Motin error = sysctl_handle_int(oidp, &arg, 0, req);
718461a98a2SAlexander Motin if (!error && req->newptr != NULL)
719461a98a2SAlexander Motin error = acpi_asus_wmi_sysctl_set(sc, dev_id, arg, oldarg);
720461a98a2SAlexander Motin ACPI_SERIAL_END(asus_wmi);
721461a98a2SAlexander Motin
722461a98a2SAlexander Motin return (error);
723461a98a2SAlexander Motin }
724461a98a2SAlexander Motin
725461a98a2SAlexander Motin static int
acpi_asus_wmi_sysctl_get(struct acpi_asus_wmi_softc * sc,int dev_id)726461a98a2SAlexander Motin acpi_asus_wmi_sysctl_get(struct acpi_asus_wmi_softc *sc, int dev_id)
727461a98a2SAlexander Motin {
728461a98a2SAlexander Motin UINT32 val = 0;
729461a98a2SAlexander Motin
730461a98a2SAlexander Motin ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
731461a98a2SAlexander Motin ACPI_SERIAL_ASSERT(asus_wmi);
732461a98a2SAlexander Motin
733*027b93c2SVladimir Kondratyev switch(dev_id) {
734*027b93c2SVladimir Kondratyev case ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY:
735*027b93c2SVladimir Kondratyev return (sc->ttp_mode);
736*027b93c2SVladimir Kondratyev default:
737*027b93c2SVladimir Kondratyev break;
738*027b93c2SVladimir Kondratyev }
739*027b93c2SVladimir Kondratyev
740461a98a2SAlexander Motin acpi_wpi_asus_get_devstate(sc, dev_id, &val);
741461a98a2SAlexander Motin
742461a98a2SAlexander Motin switch(dev_id) {
743461a98a2SAlexander Motin case ASUS_WMI_DEVID_THERMAL_CTRL:
7449d6672e1SLuiz Otavio O Souza val = (val - 2731 + 5) / 10;
745461a98a2SAlexander Motin break;
746461a98a2SAlexander Motin case ASUS_WMI_DEVID_PROCESSOR_STATE:
747461a98a2SAlexander Motin case ASUS_WMI_DEVID_FAN_CTRL:
748461a98a2SAlexander Motin break;
749461a98a2SAlexander Motin case ASUS_WMI_DEVID_BRIGHTNESS:
750461a98a2SAlexander Motin val &= ASUS_WMI_DSTS_BRIGHTNESS_MASK;
751461a98a2SAlexander Motin break;
752461a98a2SAlexander Motin case ASUS_WMI_DEVID_KBD_BACKLIGHT:
753f134662aSVladimir Kondratyev val &= 0x3;
754461a98a2SAlexander Motin break;
755461a98a2SAlexander Motin default:
756461a98a2SAlexander Motin if (val & ASUS_WMI_DSTS_UNKNOWN_BIT)
757461a98a2SAlexander Motin val = -1;
758461a98a2SAlexander Motin else
759461a98a2SAlexander Motin val = !!(val & ASUS_WMI_DSTS_STATUS_BIT);
760461a98a2SAlexander Motin break;
761461a98a2SAlexander Motin }
762461a98a2SAlexander Motin
763461a98a2SAlexander Motin return (val);
764461a98a2SAlexander Motin }
765461a98a2SAlexander Motin
766461a98a2SAlexander Motin static int
acpi_asus_wmi_sysctl_set(struct acpi_asus_wmi_softc * sc,int dev_id,int arg,int oldarg)767461a98a2SAlexander Motin acpi_asus_wmi_sysctl_set(struct acpi_asus_wmi_softc *sc, int dev_id, int arg, int oldarg)
768461a98a2SAlexander Motin {
769461a98a2SAlexander Motin ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
770461a98a2SAlexander Motin ACPI_SERIAL_ASSERT(asus_wmi);
771461a98a2SAlexander Motin
772461a98a2SAlexander Motin switch(dev_id) {
773461a98a2SAlexander Motin case ASUS_WMI_DEVID_KBD_BACKLIGHT:
774f134662aSVladimir Kondratyev arg = min(0x3, arg);
775461a98a2SAlexander Motin if (arg != 0)
776461a98a2SAlexander Motin arg |= 0x80;
777461a98a2SAlexander Motin break;
778*027b93c2SVladimir Kondratyev case ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY:
779*027b93c2SVladimir Kondratyev arg = min(0x2, arg);
780*027b93c2SVladimir Kondratyev sc->ttp_mode = arg;
781*027b93c2SVladimir Kondratyev break;
782461a98a2SAlexander Motin }
783461a98a2SAlexander Motin
784461a98a2SAlexander Motin acpi_wpi_asus_set_devstate(sc, dev_id, arg, NULL);
785461a98a2SAlexander Motin
786461a98a2SAlexander Motin return (0);
787461a98a2SAlexander Motin }
788461a98a2SAlexander Motin
789461a98a2SAlexander Motin static __inline void
acpi_asus_wmi_free_buffer(ACPI_BUFFER * buf)790461a98a2SAlexander Motin acpi_asus_wmi_free_buffer(ACPI_BUFFER* buf) {
791461a98a2SAlexander Motin if (buf && buf->Pointer) {
792461a98a2SAlexander Motin AcpiOsFree(buf->Pointer);
793461a98a2SAlexander Motin }
794461a98a2SAlexander Motin }
795461a98a2SAlexander Motin
796d5bf6a72SVladimir Kondratyev static int
acpi_asus_wmi_get_event_code(device_t wmi_dev,UINT32 notify,int * code)797d5bf6a72SVladimir Kondratyev acpi_asus_wmi_get_event_code(device_t wmi_dev, UINT32 notify, int *code)
798d5bf6a72SVladimir Kondratyev {
799d5bf6a72SVladimir Kondratyev ACPI_BUFFER response = { ACPI_ALLOCATE_BUFFER, NULL };
800d5bf6a72SVladimir Kondratyev ACPI_OBJECT *obj;
801d5bf6a72SVladimir Kondratyev int error = 0;
802d5bf6a72SVladimir Kondratyev
803d5bf6a72SVladimir Kondratyev if (ACPI_FAILURE(ACPI_WMI_GET_EVENT_DATA(wmi_dev, notify, &response)))
804d5bf6a72SVladimir Kondratyev return (EIO);
805d5bf6a72SVladimir Kondratyev obj = (ACPI_OBJECT*) response.Pointer;
806d5bf6a72SVladimir Kondratyev if (obj && obj->Type == ACPI_TYPE_INTEGER)
807d5bf6a72SVladimir Kondratyev *code = obj->Integer.Value & ASUS_WMI_EVENT_MASK;
808d5bf6a72SVladimir Kondratyev else
809d5bf6a72SVladimir Kondratyev error = EINVAL;
810d5bf6a72SVladimir Kondratyev acpi_asus_wmi_free_buffer(&response);
811d5bf6a72SVladimir Kondratyev return (error);
812d5bf6a72SVladimir Kondratyev }
813d5bf6a72SVladimir Kondratyev
8145e41194bSVladimir Kondratyev #ifdef EVDEV_SUPPORT
8155e41194bSVladimir Kondratyev static void
acpi_asus_wmi_push_evdev_event(struct evdev_dev * evdev,UINT32 notify)8165e41194bSVladimir Kondratyev acpi_asus_wmi_push_evdev_event(struct evdev_dev *evdev, UINT32 notify)
8175e41194bSVladimir Kondratyev {
8185e41194bSVladimir Kondratyev int i;
8195e41194bSVladimir Kondratyev uint16_t key;
8205e41194bSVladimir Kondratyev
8215e41194bSVladimir Kondratyev for (i = 0; i < nitems(acpi_asus_wmi_evdev_map); i++) {
8225e41194bSVladimir Kondratyev if (acpi_asus_wmi_evdev_map[i].notify == notify &&
8235e41194bSVladimir Kondratyev acpi_asus_wmi_evdev_map[i].key != NO_KEY) {
8245e41194bSVladimir Kondratyev key = acpi_asus_wmi_evdev_map[i].key;
8255e41194bSVladimir Kondratyev evdev_push_key(evdev, key, 1);
8265e41194bSVladimir Kondratyev evdev_sync(evdev);
8275e41194bSVladimir Kondratyev evdev_push_key(evdev, key, 0);
8285e41194bSVladimir Kondratyev evdev_sync(evdev);
8295e41194bSVladimir Kondratyev break;
8305e41194bSVladimir Kondratyev }
8315e41194bSVladimir Kondratyev }
8325e41194bSVladimir Kondratyev }
8335e41194bSVladimir Kondratyev #endif
8345e41194bSVladimir Kondratyev
835461a98a2SAlexander Motin static void
acpi_asus_wmi_handle_event(struct acpi_asus_wmi_softc * sc,int code)836d5bf6a72SVladimir Kondratyev acpi_asus_wmi_handle_event(struct acpi_asus_wmi_softc *sc, int code)
837461a98a2SAlexander Motin {
838461a98a2SAlexander Motin UINT32 val;
839461a98a2SAlexander Motin
840d5bf6a72SVladimir Kondratyev if (code != 0) {
841461a98a2SAlexander Motin acpi_UserNotify("ASUS", ACPI_ROOT_OBJECT,
842461a98a2SAlexander Motin code);
8435e41194bSVladimir Kondratyev #ifdef EVDEV_SUPPORT
8445e41194bSVladimir Kondratyev acpi_asus_wmi_push_evdev_event(sc->evdev, code);
8455e41194bSVladimir Kondratyev #endif
846461a98a2SAlexander Motin }
847461a98a2SAlexander Motin if (code && sc->handle_keys) {
848461a98a2SAlexander Motin /* Keyboard backlight control. */
849461a98a2SAlexander Motin if (code == 0xc4 || code == 0xc5) {
850461a98a2SAlexander Motin acpi_wpi_asus_get_devstate(sc,
851461a98a2SAlexander Motin ASUS_WMI_DEVID_KBD_BACKLIGHT, &val);
852f134662aSVladimir Kondratyev val &= 0x3;
853461a98a2SAlexander Motin if (code == 0xc4) {
854f134662aSVladimir Kondratyev if (val < 0x3)
855461a98a2SAlexander Motin val++;
856461a98a2SAlexander Motin } else if (val > 0)
857461a98a2SAlexander Motin val--;
858461a98a2SAlexander Motin if (val != 0)
859461a98a2SAlexander Motin val |= 0x80;
860461a98a2SAlexander Motin acpi_wpi_asus_set_devstate(sc,
861461a98a2SAlexander Motin ASUS_WMI_DEVID_KBD_BACKLIGHT, val, NULL);
862f134662aSVladimir Kondratyev sc->kbd_bkl_level = devstate_to_kbd_bkl_level(val);
863461a98a2SAlexander Motin }
864461a98a2SAlexander Motin /* Touchpad control. */
865461a98a2SAlexander Motin if (code == 0x6b) {
866461a98a2SAlexander Motin acpi_wpi_asus_get_devstate(sc,
867461a98a2SAlexander Motin ASUS_WMI_DEVID_TOUCHPAD, &val);
868461a98a2SAlexander Motin val = !(val & 1);
869461a98a2SAlexander Motin acpi_wpi_asus_set_devstate(sc,
870461a98a2SAlexander Motin ASUS_WMI_DEVID_TOUCHPAD, val, NULL);
871461a98a2SAlexander Motin }
872*027b93c2SVladimir Kondratyev /* Throttle thermal policy control. */
873*027b93c2SVladimir Kondratyev if (code == 0xae) {
874*027b93c2SVladimir Kondratyev sc->ttp_mode++;
875*027b93c2SVladimir Kondratyev if (sc->ttp_mode > 2)
876*027b93c2SVladimir Kondratyev sc->ttp_mode = 0;
877*027b93c2SVladimir Kondratyev acpi_wpi_asus_set_devstate(sc,
878*027b93c2SVladimir Kondratyev ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY,
879*027b93c2SVladimir Kondratyev sc->ttp_mode, NULL);
880*027b93c2SVladimir Kondratyev }
881*027b93c2SVladimir Kondratyev /* TUF laptop RGB mode control. */
882*027b93c2SVladimir Kondratyev if (code == 0xb3) {
883*027b93c2SVladimir Kondratyev const uint32_t cmd = 0xb4; /* Save to BIOS */
884*027b93c2SVladimir Kondratyev const uint32_t r = 0xff, g = 0xff, b = 0xff;
885*027b93c2SVladimir Kondratyev const uint32_t speed = 0xeb; /* Medium */
886*027b93c2SVladimir Kondratyev if (sc->tuf_rgb_mode < 2)
887*027b93c2SVladimir Kondratyev sc->tuf_rgb_mode++;
888*027b93c2SVladimir Kondratyev else if (sc->tuf_rgb_mode == 2)
889*027b93c2SVladimir Kondratyev sc->tuf_rgb_mode = 10;
890*027b93c2SVladimir Kondratyev else sc->tuf_rgb_mode = 0;
891*027b93c2SVladimir Kondratyev acpi_asus_wmi_evaluate_method(sc->wmi_dev,
892*027b93c2SVladimir Kondratyev ASUS_WMI_METHODID_DEVS,
893*027b93c2SVladimir Kondratyev ASUS_WMI_DEVID_TUF_RGB_MODE,
894*027b93c2SVladimir Kondratyev cmd | (sc->tuf_rgb_mode << 8) | (r << 16) | (g << 24),
895*027b93c2SVladimir Kondratyev b | (speed << 8), NULL);
896*027b93c2SVladimir Kondratyev }
897461a98a2SAlexander Motin }
898d5bf6a72SVladimir Kondratyev }
899d5bf6a72SVladimir Kondratyev
900d5bf6a72SVladimir Kondratyev static void
acpi_asus_wmi_notify(ACPI_HANDLE h,UINT32 notify,void * context)901d5bf6a72SVladimir Kondratyev acpi_asus_wmi_notify(ACPI_HANDLE h, UINT32 notify, void *context)
902d5bf6a72SVladimir Kondratyev {
903d5bf6a72SVladimir Kondratyev device_t dev = context;
904d5bf6a72SVladimir Kondratyev struct acpi_asus_wmi_softc *sc = device_get_softc(dev);
905d5bf6a72SVladimir Kondratyev int code = 0, i = 1;
906d5bf6a72SVladimir Kondratyev
907d5bf6a72SVladimir Kondratyev ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify);
908d5bf6a72SVladimir Kondratyev
909d5bf6a72SVladimir Kondratyev if (sc->event_queue)
910d5bf6a72SVladimir Kondratyev i += ASUS_WMI_EVENT_QUEUE_SIZE;
911d5bf6a72SVladimir Kondratyev do {
912d5bf6a72SVladimir Kondratyev if (acpi_asus_wmi_get_event_code(sc->wmi_dev, notify, &code)
913d5bf6a72SVladimir Kondratyev != 0) {
914d5bf6a72SVladimir Kondratyev device_printf(dev, "Failed to get event code\n");
915d5bf6a72SVladimir Kondratyev return;
916d5bf6a72SVladimir Kondratyev }
917d5bf6a72SVladimir Kondratyev if (code == ASUS_WMI_EVENT_QUEUE_END ||
918d5bf6a72SVladimir Kondratyev code == ASUS_WMI_EVENT_MASK)
919d5bf6a72SVladimir Kondratyev return;
920d5bf6a72SVladimir Kondratyev acpi_asus_wmi_handle_event(sc, code);
921d5bf6a72SVladimir Kondratyev if (notify != ASUS_WMI_EVENT_VALUE_ATK)
922d5bf6a72SVladimir Kondratyev return;
923d5bf6a72SVladimir Kondratyev } while (--i != 0);
924d5bf6a72SVladimir Kondratyev if (sc->event_queue)
925d5bf6a72SVladimir Kondratyev device_printf(dev, "Can not read event queue, "
926d5bf6a72SVladimir Kondratyev "last code: 0x%x\n", code);
927461a98a2SAlexander Motin }
928461a98a2SAlexander Motin
929461a98a2SAlexander Motin static int
acpi_asus_wmi_evaluate_method(device_t wmi_dev,int method,UINT32 arg0,UINT32 arg1,UINT32 arg2,UINT32 * retval)930461a98a2SAlexander Motin acpi_asus_wmi_evaluate_method(device_t wmi_dev, int method,
931*027b93c2SVladimir Kondratyev UINT32 arg0, UINT32 arg1, UINT32 arg2, UINT32 *retval)
932461a98a2SAlexander Motin {
933*027b93c2SVladimir Kondratyev UINT32 params[3] = { arg0, arg1, arg2 };
934461a98a2SAlexander Motin UINT32 result;
935461a98a2SAlexander Motin ACPI_OBJECT *obj;
936461a98a2SAlexander Motin ACPI_BUFFER in = { sizeof(params), ¶ms };
937461a98a2SAlexander Motin ACPI_BUFFER out = { ACPI_ALLOCATE_BUFFER, NULL };
938461a98a2SAlexander Motin
939461a98a2SAlexander Motin if (ACPI_FAILURE(ACPI_WMI_EVALUATE_CALL(wmi_dev,
940461a98a2SAlexander Motin ACPI_ASUS_WMI_MGMT_GUID, 1, method, &in, &out))) {
941461a98a2SAlexander Motin acpi_asus_wmi_free_buffer(&out);
942461a98a2SAlexander Motin return (-EINVAL);
943461a98a2SAlexander Motin }
944461a98a2SAlexander Motin obj = out.Pointer;
945461a98a2SAlexander Motin if (obj && obj->Type == ACPI_TYPE_INTEGER)
946461a98a2SAlexander Motin result = (UINT32) obj->Integer.Value;
947461a98a2SAlexander Motin else
948461a98a2SAlexander Motin result = 0;
949461a98a2SAlexander Motin acpi_asus_wmi_free_buffer(&out);
950461a98a2SAlexander Motin if (retval)
951461a98a2SAlexander Motin *retval = result;
952461a98a2SAlexander Motin return (result == ASUS_WMI_UNSUPPORTED_METHOD ? -ENODEV : 0);
953461a98a2SAlexander Motin }
954461a98a2SAlexander Motin
955461a98a2SAlexander Motin static int
acpi_wpi_asus_get_devstate(struct acpi_asus_wmi_softc * sc,UINT32 dev_id,UINT32 * retval)956461a98a2SAlexander Motin acpi_wpi_asus_get_devstate(struct acpi_asus_wmi_softc *sc,
957461a98a2SAlexander Motin UINT32 dev_id, UINT32 *retval)
958461a98a2SAlexander Motin {
959461a98a2SAlexander Motin
960461a98a2SAlexander Motin return (acpi_asus_wmi_evaluate_method(sc->wmi_dev,
961*027b93c2SVladimir Kondratyev sc->dsts_id, dev_id, 0, 0, retval));
962461a98a2SAlexander Motin }
963461a98a2SAlexander Motin
964461a98a2SAlexander Motin static int
acpi_wpi_asus_set_devstate(struct acpi_asus_wmi_softc * sc,UINT32 dev_id,UINT32 ctrl_param,UINT32 * retval)965461a98a2SAlexander Motin acpi_wpi_asus_set_devstate(struct acpi_asus_wmi_softc *sc,
966461a98a2SAlexander Motin UINT32 dev_id, UINT32 ctrl_param, UINT32 *retval)
967461a98a2SAlexander Motin {
968461a98a2SAlexander Motin
969461a98a2SAlexander Motin return (acpi_asus_wmi_evaluate_method(sc->wmi_dev,
970*027b93c2SVladimir Kondratyev ASUS_WMI_METHODID_DEVS, dev_id, ctrl_param, 0, retval));
971461a98a2SAlexander Motin }
972f134662aSVladimir Kondratyev
973f134662aSVladimir Kondratyev static int
acpi_asus_wmi_backlight_update_status(device_t dev,struct backlight_props * props)974f134662aSVladimir Kondratyev acpi_asus_wmi_backlight_update_status(device_t dev, struct backlight_props
975f134662aSVladimir Kondratyev *props)
976f134662aSVladimir Kondratyev {
977f134662aSVladimir Kondratyev struct acpi_asus_wmi_softc *sc = device_get_softc(dev);
978f134662aSVladimir Kondratyev
979f134662aSVladimir Kondratyev acpi_wpi_asus_set_devstate(sc, ASUS_WMI_DEVID_KBD_BACKLIGHT,
980f134662aSVladimir Kondratyev kbd_bkl_level_to_devstate(props->brightness), NULL);
981f134662aSVladimir Kondratyev sc->kbd_bkl_level = props->brightness;
982f134662aSVladimir Kondratyev
983f134662aSVladimir Kondratyev return (0);
984f134662aSVladimir Kondratyev }
985f134662aSVladimir Kondratyev
986f134662aSVladimir Kondratyev static int
acpi_asus_wmi_backlight_get_status(device_t dev,struct backlight_props * props)987f134662aSVladimir Kondratyev acpi_asus_wmi_backlight_get_status(device_t dev, struct backlight_props *props)
988f134662aSVladimir Kondratyev {
989f134662aSVladimir Kondratyev struct acpi_asus_wmi_softc *sc = device_get_softc(dev);
990f134662aSVladimir Kondratyev
991f134662aSVladimir Kondratyev props->brightness = sc->kbd_bkl_level;
992f134662aSVladimir Kondratyev props->nlevels = nitems(acpi_asus_wmi_backlight_levels);
993f134662aSVladimir Kondratyev memcpy(props->levels, acpi_asus_wmi_backlight_levels,
994f134662aSVladimir Kondratyev sizeof(acpi_asus_wmi_backlight_levels));
995f134662aSVladimir Kondratyev
996f134662aSVladimir Kondratyev return (0);
997f134662aSVladimir Kondratyev }
998f134662aSVladimir Kondratyev
999f134662aSVladimir Kondratyev static int
acpi_asus_wmi_backlight_get_info(device_t dev,struct backlight_info * info)1000f134662aSVladimir Kondratyev acpi_asus_wmi_backlight_get_info(device_t dev, struct backlight_info *info)
1001f134662aSVladimir Kondratyev {
1002f134662aSVladimir Kondratyev info->type = BACKLIGHT_TYPE_KEYBOARD;
1003f134662aSVladimir Kondratyev strlcpy(info->name, "ASUS Keyboard", BACKLIGHTMAXNAMELENGTH);
1004f134662aSVladimir Kondratyev
1005f134662aSVladimir Kondratyev return (0);
1006f134662aSVladimir Kondratyev }
1007