]>
Commit | Line | Data |
---|---|---|
1a59d1b8 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
b229ece9 CC |
2 | /* |
3 | * Asus Notebooks WMI hotkey driver | |
4 | * | |
5 | * Copyright(C) 2010 Corentin Chary <corentin.chary@gmail.com> | |
b229ece9 CC |
6 | */ |
7 | ||
8 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
9 | ||
10 | #include <linux/kernel.h> | |
11 | #include <linux/module.h> | |
12 | #include <linux/init.h> | |
13 | #include <linux/input.h> | |
14 | #include <linux/input/sparse-keymap.h> | |
fb05b9f5 | 15 | #include <linux/fb.h> |
d2044c5a | 16 | #include <linux/dmi.h> |
b5643539 | 17 | #include <linux/i8042.h> |
b229ece9 CC |
18 | |
19 | #include "asus-wmi.h" | |
20 | ||
21 | #define ASUS_NB_WMI_FILE "asus-nb-wmi" | |
22 | ||
5909c654 | 23 | MODULE_AUTHOR("Corentin Chary <corentin.chary@gmail.com>"); |
b229ece9 CC |
24 | MODULE_DESCRIPTION("Asus Notebooks WMI Hotkey Driver"); |
25 | MODULE_LICENSE("GPL"); | |
26 | ||
27 | #define ASUS_NB_WMI_EVENT_GUID "0B3CBB35-E3C2-45ED-91C2-4C5A6D195D1C" | |
28 | ||
29 | MODULE_ALIAS("wmi:"ASUS_NB_WMI_EVENT_GUID); | |
30 | ||
fddbfed5 CC |
31 | /* |
32 | * WAPF defines the behavior of the Fn+Fx wlan key | |
33 | * The significance of values is yet to be found, but | |
34 | * most of the time: | |
35 | * Bit | Bluetooth | WLAN | |
36 | * 0 | Hardware | Hardware | |
37 | * 1 | Hardware | Software | |
38 | * 4 | Software | Software | |
39 | */ | |
d2044c5a | 40 | static int wapf = -1; |
fddbfed5 CC |
41 | module_param(wapf, uint, 0444); |
42 | MODULE_PARM_DESC(wapf, "WAPF value"); | |
43 | ||
d2044c5a AK |
44 | static struct quirk_entry *quirks; |
45 | ||
b5643539 OR |
46 | static bool asus_q500a_i8042_filter(unsigned char data, unsigned char str, |
47 | struct serio *port) | |
48 | { | |
49 | static bool extended; | |
50 | bool ret = false; | |
51 | ||
52 | if (str & I8042_STR_AUXDATA) | |
53 | return false; | |
54 | ||
55 | if (unlikely(data == 0xe1)) { | |
56 | extended = true; | |
57 | ret = true; | |
58 | } else if (unlikely(extended)) { | |
59 | extended = false; | |
60 | ret = true; | |
61 | } | |
62 | ||
63 | return ret; | |
64 | } | |
65 | ||
6a2bcccd | 66 | static struct quirk_entry quirk_asus_unknown = { |
d2044c5a | 67 | .wapf = 0, |
401fee81 | 68 | .wmi_backlight_set_devstate = true, |
d2044c5a AK |
69 | }; |
70 | ||
b5643539 OR |
71 | static struct quirk_entry quirk_asus_q500a = { |
72 | .i8042_filter = asus_q500a_i8042_filter, | |
401fee81 | 73 | .wmi_backlight_set_devstate = true, |
b5643539 OR |
74 | }; |
75 | ||
a2a96f0c AK |
76 | /* |
77 | * For those machines that need software to control bt/wifi status | |
78 | * and can't adjust brightness through ACPI interface | |
79 | * and have duplicate events(ACPI and WMI) for display toggle | |
80 | */ | |
81 | static struct quirk_entry quirk_asus_x55u = { | |
82 | .wapf = 4, | |
83 | .wmi_backlight_power = true, | |
401fee81 | 84 | .wmi_backlight_set_devstate = true, |
a2a96f0c AK |
85 | .no_display_toggle = true, |
86 | }; | |
87 | ||
378008df | 88 | static struct quirk_entry quirk_asus_wapf4 = { |
d2044c5a | 89 | .wapf = 4, |
401fee81 | 90 | .wmi_backlight_set_devstate = true, |
d2044c5a AK |
91 | }; |
92 | ||
c66263a3 AK |
93 | static struct quirk_entry quirk_asus_x200ca = { |
94 | .wapf = 2, | |
401fee81 | 95 | .wmi_backlight_set_devstate = true, |
c66263a3 AK |
96 | }; |
97 | ||
999d4376 | 98 | static struct quirk_entry quirk_asus_ux303ub = { |
99 | .wmi_backlight_native = true, | |
401fee81 | 100 | .wmi_backlight_set_devstate = true, |
999d4376 | 101 | }; |
102 | ||
8023eff1 | 103 | static struct quirk_entry quirk_asus_x550lb = { |
401fee81 | 104 | .wmi_backlight_set_devstate = true, |
8023eff1 KCH |
105 | .xusb2pr = 0x01D9, |
106 | }; | |
107 | ||
db2582af | 108 | static struct quirk_entry quirk_asus_forceals = { |
401fee81 | 109 | .wmi_backlight_set_devstate = true, |
e9b61518 OR |
110 | .wmi_force_als_set = true, |
111 | }; | |
112 | ||
d2044c5a AK |
113 | static int dmi_matched(const struct dmi_system_id *dmi) |
114 | { | |
085370eb | 115 | pr_info("Identified laptop model '%s'\n", dmi->ident); |
d2044c5a AK |
116 | quirks = dmi->driver_data; |
117 | return 1; | |
118 | } | |
119 | ||
55d1e9d8 | 120 | static const struct dmi_system_id asus_quirks[] = { |
b5643539 OR |
121 | { |
122 | .callback = dmi_matched, | |
123 | .ident = "ASUSTeK COMPUTER INC. Q500A", | |
124 | .matches = { | |
125 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
126 | DMI_MATCH(DMI_PRODUCT_NAME, "Q500A"), | |
127 | }, | |
128 | .driver_data = &quirk_asus_q500a, | |
129 | }, | |
831a444e HG |
130 | { |
131 | .callback = dmi_matched, | |
132 | .ident = "ASUSTeK COMPUTER INC. U32U", | |
133 | .matches = { | |
134 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), | |
135 | DMI_MATCH(DMI_PRODUCT_NAME, "U32U"), | |
136 | }, | |
137 | /* | |
138 | * Note this machine has a Brazos APU, and most Brazos Asus | |
139 | * machines need quirk_asus_x55u / wmi_backlight_power but | |
140 | * here acpi-video seems to work fine for backlight control. | |
141 | */ | |
142 | .driver_data = &quirk_asus_wapf4, | |
143 | }, | |
f3582361 ST |
144 | { |
145 | .callback = dmi_matched, | |
146 | .ident = "ASUSTeK COMPUTER INC. X302UA", | |
147 | .matches = { | |
148 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
149 | DMI_MATCH(DMI_PRODUCT_NAME, "X302UA"), | |
150 | }, | |
151 | .driver_data = &quirk_asus_wapf4, | |
152 | }, | |
d2044c5a AK |
153 | { |
154 | .callback = dmi_matched, | |
155 | .ident = "ASUSTeK COMPUTER INC. X401U", | |
156 | .matches = { | |
157 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
158 | DMI_MATCH(DMI_PRODUCT_NAME, "X401U"), | |
159 | }, | |
a2a96f0c AK |
160 | .driver_data = &quirk_asus_x55u, |
161 | }, | |
162 | { | |
163 | .callback = dmi_matched, | |
164 | .ident = "ASUSTeK COMPUTER INC. X401A", | |
165 | .matches = { | |
166 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
167 | DMI_MATCH(DMI_PRODUCT_NAME, "X401A"), | |
168 | }, | |
378008df | 169 | .driver_data = &quirk_asus_wapf4, |
d2044c5a AK |
170 | }, |
171 | { | |
172 | .callback = dmi_matched, | |
173 | .ident = "ASUSTeK COMPUTER INC. X401A1", | |
174 | .matches = { | |
175 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
176 | DMI_MATCH(DMI_PRODUCT_NAME, "X401A1"), | |
177 | }, | |
378008df | 178 | .driver_data = &quirk_asus_wapf4, |
d2044c5a | 179 | }, |
e74e2599 MPS |
180 | { |
181 | .callback = dmi_matched, | |
182 | .ident = "ASUSTeK COMPUTER INC. X45U", | |
183 | .matches = { | |
184 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
185 | DMI_MATCH(DMI_PRODUCT_NAME, "X45U"), | |
186 | }, | |
187 | .driver_data = &quirk_asus_wapf4, | |
188 | }, | |
8901c18b DD |
189 | { |
190 | .callback = dmi_matched, | |
191 | .ident = "ASUSTeK COMPUTER INC. X456UA", | |
192 | .matches = { | |
193 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
194 | DMI_MATCH(DMI_PRODUCT_NAME, "X456UA"), | |
195 | }, | |
d1c4e9bf | 196 | .driver_data = &quirk_asus_wapf4, |
8901c18b DD |
197 | }, |
198 | { | |
199 | .callback = dmi_matched, | |
200 | .ident = "ASUSTeK COMPUTER INC. X456UF", | |
201 | .matches = { | |
202 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
203 | DMI_MATCH(DMI_PRODUCT_NAME, "X456UF"), | |
204 | }, | |
d1c4e9bf | 205 | .driver_data = &quirk_asus_wapf4, |
8901c18b | 206 | }, |
d2044c5a AK |
207 | { |
208 | .callback = dmi_matched, | |
209 | .ident = "ASUSTeK COMPUTER INC. X501U", | |
210 | .matches = { | |
211 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
212 | DMI_MATCH(DMI_PRODUCT_NAME, "X501U"), | |
213 | }, | |
a2a96f0c AK |
214 | .driver_data = &quirk_asus_x55u, |
215 | }, | |
216 | { | |
217 | .callback = dmi_matched, | |
218 | .ident = "ASUSTeK COMPUTER INC. X501A", | |
219 | .matches = { | |
220 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
221 | DMI_MATCH(DMI_PRODUCT_NAME, "X501A"), | |
222 | }, | |
378008df | 223 | .driver_data = &quirk_asus_wapf4, |
d2044c5a AK |
224 | }, |
225 | { | |
226 | .callback = dmi_matched, | |
227 | .ident = "ASUSTeK COMPUTER INC. X501A1", | |
228 | .matches = { | |
229 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
230 | DMI_MATCH(DMI_PRODUCT_NAME, "X501A1"), | |
231 | }, | |
378008df | 232 | .driver_data = &quirk_asus_wapf4, |
d2044c5a | 233 | }, |
c08db55f AU |
234 | { |
235 | .callback = dmi_matched, | |
236 | .ident = "ASUSTeK COMPUTER INC. X550CA", | |
237 | .matches = { | |
238 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
239 | DMI_MATCH(DMI_PRODUCT_NAME, "X550CA"), | |
240 | }, | |
378008df | 241 | .driver_data = &quirk_asus_wapf4, |
c08db55f | 242 | }, |
6d6ded3b HG |
243 | { |
244 | .callback = dmi_matched, | |
245 | .ident = "ASUSTeK COMPUTER INC. X550CC", | |
246 | .matches = { | |
247 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
248 | DMI_MATCH(DMI_PRODUCT_NAME, "X550CC"), | |
249 | }, | |
250 | .driver_data = &quirk_asus_wapf4, | |
251 | }, | |
22ba58c8 HG |
252 | { |
253 | .callback = dmi_matched, | |
254 | .ident = "ASUSTeK COMPUTER INC. X550CL", | |
255 | .matches = { | |
256 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
257 | DMI_MATCH(DMI_PRODUCT_NAME, "X550CL"), | |
258 | }, | |
259 | .driver_data = &quirk_asus_wapf4, | |
260 | }, | |
4ec7a45b SG |
261 | { |
262 | .callback = dmi_matched, | |
263 | .ident = "ASUSTeK COMPUTER INC. X550VB", | |
264 | .matches = { | |
265 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
266 | DMI_MATCH(DMI_PRODUCT_NAME, "X550VB"), | |
267 | }, | |
268 | .driver_data = &quirk_asus_wapf4, | |
269 | }, | |
841e11cc HG |
270 | { |
271 | .callback = dmi_matched, | |
272 | .ident = "ASUSTeK COMPUTER INC. X551CA", | |
273 | .matches = { | |
274 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
275 | DMI_MATCH(DMI_PRODUCT_NAME, "X551CA"), | |
276 | }, | |
277 | .driver_data = &quirk_asus_wapf4, | |
278 | }, | |
d2044c5a AK |
279 | { |
280 | .callback = dmi_matched, | |
281 | .ident = "ASUSTeK COMPUTER INC. X55A", | |
282 | .matches = { | |
283 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
284 | DMI_MATCH(DMI_PRODUCT_NAME, "X55A"), | |
285 | }, | |
378008df | 286 | .driver_data = &quirk_asus_wapf4, |
d2044c5a AK |
287 | }, |
288 | { | |
289 | .callback = dmi_matched, | |
290 | .ident = "ASUSTeK COMPUTER INC. X55C", | |
291 | .matches = { | |
292 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
293 | DMI_MATCH(DMI_PRODUCT_NAME, "X55C"), | |
294 | }, | |
378008df | 295 | .driver_data = &quirk_asus_wapf4, |
d2044c5a AK |
296 | }, |
297 | { | |
298 | .callback = dmi_matched, | |
299 | .ident = "ASUSTeK COMPUTER INC. X55U", | |
300 | .matches = { | |
301 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
302 | DMI_MATCH(DMI_PRODUCT_NAME, "X55U"), | |
303 | }, | |
a2a96f0c | 304 | .driver_data = &quirk_asus_x55u, |
d2044c5a AK |
305 | }, |
306 | { | |
307 | .callback = dmi_matched, | |
308 | .ident = "ASUSTeK COMPUTER INC. X55VD", | |
309 | .matches = { | |
310 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
311 | DMI_MATCH(DMI_PRODUCT_NAME, "X55VD"), | |
312 | }, | |
378008df | 313 | .driver_data = &quirk_asus_wapf4, |
a849e002 AK |
314 | }, |
315 | { | |
316 | .callback = dmi_matched, | |
317 | .ident = "ASUSTeK COMPUTER INC. X75A", | |
318 | .matches = { | |
319 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
320 | DMI_MATCH(DMI_PRODUCT_NAME, "X75A"), | |
321 | }, | |
378008df | 322 | .driver_data = &quirk_asus_wapf4, |
d2044c5a | 323 | }, |
7216e102 | 324 | { |
325 | .callback = dmi_matched, | |
326 | .ident = "ASUSTeK COMPUTER INC. X75VBP", | |
327 | .matches = { | |
328 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
329 | DMI_MATCH(DMI_PRODUCT_NAME, "X75VBP"), | |
330 | }, | |
378008df | 331 | .driver_data = &quirk_asus_wapf4, |
7216e102 | 332 | }, |
46707687 ON |
333 | { |
334 | .callback = dmi_matched, | |
335 | .ident = "ASUSTeK COMPUTER INC. X75VD", | |
336 | .matches = { | |
337 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
338 | DMI_MATCH(DMI_PRODUCT_NAME, "X75VD"), | |
339 | }, | |
340 | .driver_data = &quirk_asus_wapf4, | |
341 | }, | |
144a19ac AK |
342 | { |
343 | .callback = dmi_matched, | |
344 | .ident = "ASUSTeK COMPUTER INC. 1015E", | |
345 | .matches = { | |
346 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
347 | DMI_MATCH(DMI_PRODUCT_NAME, "1015E"), | |
348 | }, | |
378008df | 349 | .driver_data = &quirk_asus_wapf4, |
144a19ac AK |
350 | }, |
351 | { | |
352 | .callback = dmi_matched, | |
353 | .ident = "ASUSTeK COMPUTER INC. 1015U", | |
354 | .matches = { | |
355 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
356 | DMI_MATCH(DMI_PRODUCT_NAME, "1015U"), | |
357 | }, | |
378008df | 358 | .driver_data = &quirk_asus_wapf4, |
144a19ac | 359 | }, |
c66263a3 AK |
360 | { |
361 | .callback = dmi_matched, | |
362 | .ident = "ASUSTeK COMPUTER INC. X200CA", | |
363 | .matches = { | |
364 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
365 | DMI_MATCH(DMI_PRODUCT_NAME, "X200CA"), | |
366 | }, | |
367 | .driver_data = &quirk_asus_x200ca, | |
368 | }, | |
999d4376 | 369 | { |
370 | .callback = dmi_matched, | |
371 | .ident = "ASUSTeK COMPUTER INC. UX303UB", | |
372 | .matches = { | |
373 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
374 | DMI_MATCH(DMI_PRODUCT_NAME, "UX303UB"), | |
375 | }, | |
376 | .driver_data = &quirk_asus_ux303ub, | |
377 | }, | |
e9b61518 OR |
378 | { |
379 | .callback = dmi_matched, | |
380 | .ident = "ASUSTeK COMPUTER INC. UX330UAK", | |
381 | .matches = { | |
382 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
383 | DMI_MATCH(DMI_PRODUCT_NAME, "UX330UAK"), | |
384 | }, | |
db2582af | 385 | .driver_data = &quirk_asus_forceals, |
e9b61518 | 386 | }, |
8023eff1 KCH |
387 | { |
388 | .callback = dmi_matched, | |
389 | .ident = "ASUSTeK COMPUTER INC. X550LB", | |
390 | .matches = { | |
391 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
392 | DMI_MATCH(DMI_PRODUCT_NAME, "X550LB"), | |
393 | }, | |
394 | .driver_data = &quirk_asus_x550lb, | |
395 | }, | |
db2582af KH |
396 | { |
397 | .callback = dmi_matched, | |
398 | .ident = "ASUSTeK COMPUTER INC. UX430UQ", | |
399 | .matches = { | |
400 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
401 | DMI_MATCH(DMI_PRODUCT_NAME, "UX430UQ"), | |
402 | }, | |
403 | .driver_data = &quirk_asus_forceals, | |
404 | }, | |
02a5e9bc KK |
405 | { |
406 | .callback = dmi_matched, | |
407 | .ident = "ASUSTeK COMPUTER INC. UX430UNR", | |
408 | .matches = { | |
409 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
410 | DMI_MATCH(DMI_PRODUCT_NAME, "UX430UNR"), | |
411 | }, | |
412 | .driver_data = &quirk_asus_forceals, | |
413 | }, | |
d2044c5a | 414 | {}, |
6a2bcccd CC |
415 | }; |
416 | ||
fddbfed5 CC |
417 | static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver) |
418 | { | |
b5643539 OR |
419 | int ret; |
420 | ||
d2044c5a AK |
421 | quirks = &quirk_asus_unknown; |
422 | dmi_check_system(asus_quirks); | |
423 | ||
424 | driver->quirks = quirks; | |
fb05b9f5 | 425 | driver->panel_power = FB_BLANK_UNBLANK; |
d2044c5a AK |
426 | |
427 | /* overwrite the wapf setting if the wapf paramater is specified */ | |
428 | if (wapf != -1) | |
429 | quirks->wapf = wapf; | |
430 | else | |
431 | wapf = quirks->wapf; | |
b5643539 OR |
432 | |
433 | if (quirks->i8042_filter) { | |
434 | ret = i8042_install_filter(quirks->i8042_filter); | |
435 | if (ret) { | |
436 | pr_warn("Unable to install key filter\n"); | |
437 | return; | |
438 | } | |
439 | pr_info("Using i8042 filter function for receiving events\n"); | |
440 | } | |
fddbfed5 CC |
441 | } |
442 | ||
b229ece9 | 443 | static const struct key_entry asus_nb_wmi_keymap[] = { |
3ba0302b CC |
444 | { KE_KEY, ASUS_WMI_BRN_DOWN, { KEY_BRIGHTNESSDOWN } }, |
445 | { KE_KEY, ASUS_WMI_BRN_UP, { KEY_BRIGHTNESSUP } }, | |
b229ece9 CC |
446 | { KE_KEY, 0x30, { KEY_VOLUMEUP } }, |
447 | { KE_KEY, 0x31, { KEY_VOLUMEDOWN } }, | |
448 | { KE_KEY, 0x32, { KEY_MUTE } }, | |
b3f2f379 | 449 | { KE_KEY, 0x35, { KEY_SCREENLOCK } }, |
b229ece9 CC |
450 | { KE_KEY, 0x40, { KEY_PREVIOUSSONG } }, |
451 | { KE_KEY, 0x41, { KEY_NEXTSONG } }, | |
a935eaec | 452 | { KE_KEY, 0x43, { KEY_STOPCD } }, /* Stop/Eject */ |
b229ece9 | 453 | { KE_KEY, 0x45, { KEY_PLAYPAUSE } }, |
a935eaec | 454 | { KE_KEY, 0x4c, { KEY_MEDIA } }, /* WMP Key */ |
b229ece9 CC |
455 | { KE_KEY, 0x50, { KEY_EMAIL } }, |
456 | { KE_KEY, 0x51, { KEY_WWW } }, | |
457 | { KE_KEY, 0x55, { KEY_CALC } }, | |
9b05ea24 CC |
458 | { KE_IGNORE, 0x57, }, /* Battery mode */ |
459 | { KE_IGNORE, 0x58, }, /* AC mode */ | |
b229ece9 | 460 | { KE_KEY, 0x5C, { KEY_F15 } }, /* Power Gear key */ |
fddbfed5 CC |
461 | { KE_KEY, 0x5D, { KEY_WLAN } }, /* Wireless console Toggle */ |
462 | { KE_KEY, 0x5E, { KEY_WLAN } }, /* Wireless console Enable */ | |
463 | { KE_KEY, 0x5F, { KEY_WLAN } }, /* Wireless console Disable */ | |
98bfcb8e | 464 | { KE_KEY, 0x60, { KEY_TOUCHPAD_ON } }, |
24c8a4c4 AK |
465 | { KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD only */ |
466 | { KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT only */ | |
467 | { KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT */ | |
468 | { KE_KEY, 0x64, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV */ | |
469 | { KE_KEY, 0x65, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + TV */ | |
470 | { KE_KEY, 0x66, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV */ | |
471 | { KE_KEY, 0x67, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV */ | |
b229ece9 | 472 | { KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } }, |
982d385a | 473 | { KE_IGNORE, 0x6E, }, /* Low Battery notification */ |
a3e2b51c | 474 | { KE_KEY, 0x71, { KEY_F13 } }, /* General-purpose button */ |
9ee27487 | 475 | { KE_KEY, 0x7a, { KEY_ALS_TOGGLE } }, /* Ambient Light Sensor Toggle */ |
2b5767bf | 476 | { KE_KEY, 0x7c, { KEY_MICMUTE } }, |
a935eaec CC |
477 | { KE_KEY, 0x7D, { KEY_BLUETOOTH } }, /* Bluetooth Enable */ |
478 | { KE_KEY, 0x7E, { KEY_BLUETOOTH } }, /* Bluetooth Disable */ | |
b229ece9 | 479 | { KE_KEY, 0x82, { KEY_CAMERA } }, |
a935eaec CC |
480 | { KE_KEY, 0x88, { KEY_RFKILL } }, /* Radio Toggle Key */ |
481 | { KE_KEY, 0x8A, { KEY_PROG1 } }, /* Color enhancement mode */ | |
24c8a4c4 AK |
482 | { KE_KEY, 0x8C, { KEY_SWITCHVIDEOMODE } }, /* SDSP DVI only */ |
483 | { KE_KEY, 0x8D, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + DVI */ | |
484 | { KE_KEY, 0x8E, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + DVI */ | |
485 | { KE_KEY, 0x8F, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV + DVI */ | |
486 | { KE_KEY, 0x90, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + DVI */ | |
487 | { KE_KEY, 0x91, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + TV + DVI */ | |
488 | { KE_KEY, 0x92, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV + DVI */ | |
489 | { KE_KEY, 0x93, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV + DVI */ | |
b229ece9 | 490 | { KE_KEY, 0x95, { KEY_MEDIA } }, |
2b5767bf | 491 | { KE_KEY, 0x99, { KEY_PHONE } }, /* Conflicts with fan mode switch */ |
3766054f AK |
492 | { KE_KEY, 0xA0, { KEY_SWITCHVIDEOMODE } }, /* SDSP HDMI only */ |
493 | { KE_KEY, 0xA1, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + HDMI */ | |
494 | { KE_KEY, 0xA2, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + HDMI */ | |
495 | { KE_KEY, 0xA3, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV + HDMI */ | |
24c8a4c4 AK |
496 | { KE_KEY, 0xA4, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + HDMI */ |
497 | { KE_KEY, 0xA5, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + TV + HDMI */ | |
498 | { KE_KEY, 0xA6, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV + HDMI */ | |
499 | { KE_KEY, 0xA7, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV + HDMI */ | |
a935eaec CC |
500 | { KE_KEY, 0xB5, { KEY_CALC } }, |
501 | { KE_KEY, 0xC4, { KEY_KBDILLUMUP } }, | |
502 | { KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } }, | |
3aabf444 | 503 | { KE_IGNORE, 0xC6, }, /* Ambient Light Sensor notification */ |
880b29ac | 504 | { KE_KEY, 0xFA, { KEY_PROG2 } }, /* Lid flip action */ |
b229ece9 CC |
505 | { KE_END, 0}, |
506 | }; | |
507 | ||
508 | static struct asus_wmi_driver asus_nb_wmi_driver = { | |
509 | .name = ASUS_NB_WMI_FILE, | |
510 | .owner = THIS_MODULE, | |
511 | .event_guid = ASUS_NB_WMI_EVENT_GUID, | |
512 | .keymap = asus_nb_wmi_keymap, | |
513 | .input_name = "Asus WMI hotkeys", | |
514 | .input_phys = ASUS_NB_WMI_FILE "/input0", | |
c87992d1 | 515 | .detect_quirks = asus_nb_wmi_quirks, |
b229ece9 CC |
516 | }; |
517 | ||
3bd12da7 HG |
518 | static const struct dmi_system_id asus_nb_wmi_blacklist[] __initconst = { |
519 | { | |
520 | /* | |
521 | * asus-nb-wm adds no functionality. The T100TA has a detachable | |
522 | * USB kbd, so no hotkeys and it has no WMI rfkill; and loading | |
523 | * asus-nb-wm causes the camera LED to turn and _stay_ on. | |
524 | */ | |
525 | .matches = { | |
526 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
527 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"), | |
528 | }, | |
529 | }, | |
530 | { | |
531 | /* The Asus T200TA has the same issue as the T100TA */ | |
532 | .matches = { | |
533 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
534 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T200TA"), | |
535 | }, | |
536 | }, | |
537 | {} /* Terminating entry */ | |
538 | }; | |
b229ece9 CC |
539 | |
540 | static int __init asus_nb_wmi_init(void) | |
541 | { | |
3bd12da7 HG |
542 | if (dmi_check_system(asus_nb_wmi_blacklist)) |
543 | return -ENODEV; | |
544 | ||
b229ece9 CC |
545 | return asus_wmi_register_driver(&asus_nb_wmi_driver); |
546 | } | |
547 | ||
548 | static void __exit asus_nb_wmi_exit(void) | |
549 | { | |
550 | asus_wmi_unregister_driver(&asus_nb_wmi_driver); | |
551 | } | |
552 | ||
553 | module_init(asus_nb_wmi_init); | |
554 | module_exit(asus_nb_wmi_exit); |