dell-wmi: enable receiving WMI events on Dell Vostro V131
[linux-2.6-block.git] / drivers / platform / x86 / dell-wmi.c
1 /*
2  * Dell WMI hotkeys
3  *
4  * Copyright (C) 2008 Red Hat <mjg@redhat.com>
5  * Copyright (C) 2014-2015 Pali Rohár <pali.rohar@gmail.com>
6  *
7  * Portions based on wistron_btns.c:
8  * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
9  * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
10  * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 2 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, write to the Free Software
24  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25  */
26
27 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
28
29 #include <linux/kernel.h>
30 #include <linux/module.h>
31 #include <linux/init.h>
32 #include <linux/slab.h>
33 #include <linux/types.h>
34 #include <linux/input.h>
35 #include <linux/input/sparse-keymap.h>
36 #include <linux/acpi.h>
37 #include <linux/string.h>
38 #include <linux/dmi.h>
39 #include <acpi/video.h>
40 #include "dell-smbios.h"
41
42 MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
43 MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
44 MODULE_DESCRIPTION("Dell laptop WMI hotkeys driver");
45 MODULE_LICENSE("GPL");
46
47 #define DELL_EVENT_GUID "9DBB5994-A997-11DA-B012-B622A1EF5492"
48 #define DELL_DESCRIPTOR_GUID "8D9DDCBC-A997-11DA-B012-B622A1EF5492"
49
50 static u32 dell_wmi_interface_version;
51 static bool wmi_requires_smbios_request;
52
53 MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
54 MODULE_ALIAS("wmi:"DELL_DESCRIPTOR_GUID);
55
56 static int __init dmi_matched(const struct dmi_system_id *dmi)
57 {
58         wmi_requires_smbios_request = 1;
59         return 1;
60 }
61
62 static const struct dmi_system_id dell_wmi_smbios_list[] __initconst = {
63         {
64                 .callback = dmi_matched,
65                 .ident = "Dell Vostro V131",
66                 .matches = {
67                         DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
68                         DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"),
69                 },
70         },
71         { }
72 };
73
74 /*
75  * Certain keys are flagged as KE_IGNORE. All of these are either
76  * notifications (rather than requests for change) or are also sent
77  * via the keyboard controller so should not be sent again.
78  */
79
80 static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
81         { KE_IGNORE, 0x003a, { KEY_CAPSLOCK } },
82
83         { KE_KEY, 0xe045, { KEY_PROG1 } },
84         { KE_KEY, 0xe009, { KEY_EJECTCD } },
85
86         /* These also contain the brightness level at offset 6 */
87         { KE_KEY, 0xe006, { KEY_BRIGHTNESSUP } },
88         { KE_KEY, 0xe005, { KEY_BRIGHTNESSDOWN } },
89
90         /* Battery health status button */
91         { KE_KEY, 0xe007, { KEY_BATTERY } },
92
93         /* Radio devices state change */
94         { KE_IGNORE, 0xe008, { KEY_RFKILL } },
95
96         /* The next device is at offset 6, the active devices are at
97            offset 8 and the attached devices at offset 10 */
98         { KE_KEY, 0xe00b, { KEY_SWITCHVIDEOMODE } },
99
100         { KE_IGNORE, 0xe00c, { KEY_KBDILLUMTOGGLE } },
101
102         /* BIOS error detected */
103         { KE_IGNORE, 0xe00d, { KEY_RESERVED } },
104
105         /* Wifi Catcher */
106         { KE_KEY, 0xe011, {KEY_PROG2 } },
107
108         /* Ambient light sensor toggle */
109         { KE_IGNORE, 0xe013, { KEY_RESERVED } },
110
111         { KE_IGNORE, 0xe020, { KEY_MUTE } },
112
113         /* Shortcut and audio panel keys */
114         { KE_IGNORE, 0xe025, { KEY_RESERVED } },
115         { KE_IGNORE, 0xe026, { KEY_RESERVED } },
116
117         { KE_IGNORE, 0xe02e, { KEY_VOLUMEDOWN } },
118         { KE_IGNORE, 0xe030, { KEY_VOLUMEUP } },
119         { KE_IGNORE, 0xe033, { KEY_KBDILLUMUP } },
120         { KE_IGNORE, 0xe034, { KEY_KBDILLUMDOWN } },
121         { KE_IGNORE, 0xe03a, { KEY_CAPSLOCK } },
122         { KE_IGNORE, 0xe045, { KEY_NUMLOCK } },
123         { KE_IGNORE, 0xe046, { KEY_SCROLLLOCK } },
124         { KE_IGNORE, 0xe0f7, { KEY_MUTE } },
125         { KE_IGNORE, 0xe0f8, { KEY_VOLUMEDOWN } },
126         { KE_IGNORE, 0xe0f9, { KEY_VOLUMEUP } },
127         { KE_END, 0 }
128 };
129
130 static bool dell_new_hk_type;
131
132 struct dell_bios_keymap_entry {
133         u16 scancode;
134         u16 keycode;
135 };
136
137 struct dell_bios_hotkey_table {
138         struct dmi_header header;
139         struct dell_bios_keymap_entry keymap[];
140
141 };
142
143 struct dell_dmi_results {
144         int err;
145         struct key_entry *keymap;
146 };
147
148 /* Uninitialized entries here are KEY_RESERVED == 0. */
149 static const u16 bios_to_linux_keycode[256] __initconst = {
150         [0]     = KEY_MEDIA,
151         [1]     = KEY_NEXTSONG,
152         [2]     = KEY_PLAYPAUSE,
153         [3]     = KEY_PREVIOUSSONG,
154         [4]     = KEY_STOPCD,
155         [5]     = KEY_UNKNOWN,
156         [6]     = KEY_UNKNOWN,
157         [7]     = KEY_UNKNOWN,
158         [8]     = KEY_WWW,
159         [9]     = KEY_UNKNOWN,
160         [10]    = KEY_VOLUMEDOWN,
161         [11]    = KEY_MUTE,
162         [12]    = KEY_VOLUMEUP,
163         [13]    = KEY_UNKNOWN,
164         [14]    = KEY_BATTERY,
165         [15]    = KEY_EJECTCD,
166         [16]    = KEY_UNKNOWN,
167         [17]    = KEY_SLEEP,
168         [18]    = KEY_PROG1,
169         [19]    = KEY_BRIGHTNESSDOWN,
170         [20]    = KEY_BRIGHTNESSUP,
171         [21]    = KEY_UNKNOWN,
172         [22]    = KEY_KBDILLUMTOGGLE,
173         [23]    = KEY_UNKNOWN,
174         [24]    = KEY_SWITCHVIDEOMODE,
175         [25]    = KEY_UNKNOWN,
176         [26]    = KEY_UNKNOWN,
177         [27]    = KEY_SWITCHVIDEOMODE,
178         [28]    = KEY_UNKNOWN,
179         [29]    = KEY_UNKNOWN,
180         [30]    = KEY_PROG2,
181         [31]    = KEY_UNKNOWN,
182         [32]    = KEY_UNKNOWN,
183         [33]    = KEY_UNKNOWN,
184         [34]    = KEY_UNKNOWN,
185         [35]    = KEY_UNKNOWN,
186         [36]    = KEY_UNKNOWN,
187         [37]    = KEY_UNKNOWN,
188         [38]    = KEY_MICMUTE,
189         [255]   = KEY_PROG3,
190 };
191
192 /*
193  * These are applied if the 0xB2 DMI hotkey table is present and doesn't
194  * override them.
195  */
196 static const struct key_entry dell_wmi_extra_keymap[] __initconst = {
197         /* Fn-lock */
198         { KE_IGNORE, 0x151, { KEY_RESERVED } },
199
200         /* Change keyboard illumination */
201         { KE_IGNORE, 0x152, { KEY_KBDILLUMTOGGLE } },
202
203         /*
204          * Radio disable (notify only -- there is no model for which the
205          * WMI event is supposed to trigger an action).
206          */
207         { KE_IGNORE, 0x153, { KEY_RFKILL } },
208
209         /* RGB keyboard backlight control */
210         { KE_IGNORE, 0x154, { KEY_RESERVED } },
211
212         /* Stealth mode toggle */
213         { KE_IGNORE, 0x155, { KEY_RESERVED } },
214 };
215
216 static struct input_dev *dell_wmi_input_dev;
217
218 static void dell_wmi_process_key(int reported_key)
219 {
220         const struct key_entry *key;
221
222         key = sparse_keymap_entry_from_scancode(dell_wmi_input_dev,
223                                                 reported_key);
224         if (!key) {
225                 pr_info("Unknown key with scancode 0x%x pressed\n",
226                         reported_key);
227                 return;
228         }
229
230         pr_debug("Key %x pressed\n", reported_key);
231
232         /* Don't report brightness notifications that will also come via ACPI */
233         if ((key->keycode == KEY_BRIGHTNESSUP ||
234              key->keycode == KEY_BRIGHTNESSDOWN) &&
235             acpi_video_handles_brightness_key_presses())
236                 return;
237
238         sparse_keymap_report_entry(dell_wmi_input_dev, key, 1, true);
239 }
240
241 static void dell_wmi_notify(u32 value, void *context)
242 {
243         struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
244         union acpi_object *obj;
245         acpi_status status;
246         acpi_size buffer_size;
247         u16 *buffer_entry, *buffer_end;
248         int len, i;
249
250         status = wmi_get_event_data(value, &response);
251         if (status != AE_OK) {
252                 pr_warn("bad event status 0x%x\n", status);
253                 return;
254         }
255
256         obj = (union acpi_object *)response.pointer;
257         if (!obj) {
258                 pr_warn("no response\n");
259                 return;
260         }
261
262         if (obj->type != ACPI_TYPE_BUFFER) {
263                 pr_warn("bad response type %x\n", obj->type);
264                 kfree(obj);
265                 return;
266         }
267
268         pr_debug("Received WMI event (%*ph)\n",
269                 obj->buffer.length, obj->buffer.pointer);
270
271         buffer_entry = (u16 *)obj->buffer.pointer;
272         buffer_size = obj->buffer.length/2;
273
274         if (!dell_new_hk_type) {
275                 if (buffer_size >= 3 && buffer_entry[1] == 0x0)
276                         dell_wmi_process_key(buffer_entry[2]);
277                 else if (buffer_size >= 2)
278                         dell_wmi_process_key(buffer_entry[1]);
279                 else
280                         pr_info("Received unknown WMI event\n");
281                 kfree(obj);
282                 return;
283         }
284
285         buffer_end = buffer_entry + buffer_size;
286
287         /*
288          * BIOS/ACPI on devices with WMI interface version 0 does not clear
289          * buffer before filling it. So next time when BIOS/ACPI send WMI event
290          * which is smaller as previous then it contains garbage in buffer from
291          * previous event.
292          *
293          * BIOS/ACPI on devices with WMI interface version 1 clears buffer and
294          * sometimes send more events in buffer at one call.
295          *
296          * So to prevent reading garbage from buffer we will process only first
297          * one event on devices with WMI interface version 0.
298          */
299         if (dell_wmi_interface_version == 0 && buffer_entry < buffer_end)
300                 if (buffer_end > buffer_entry + buffer_entry[0] + 1)
301                         buffer_end = buffer_entry + buffer_entry[0] + 1;
302
303         while (buffer_entry < buffer_end) {
304
305                 len = buffer_entry[0];
306                 if (len == 0)
307                         break;
308
309                 len++;
310
311                 if (buffer_entry + len > buffer_end) {
312                         pr_warn("Invalid length of WMI event\n");
313                         break;
314                 }
315
316                 pr_debug("Process buffer (%*ph)\n", len*2, buffer_entry);
317
318                 switch (buffer_entry[1]) {
319                 case 0x00:
320                         for (i = 2; i < len; ++i) {
321                                 switch (buffer_entry[i]) {
322                                 case 0xe043:
323                                         /* NIC Link is Up */
324                                         pr_debug("NIC Link is Up\n");
325                                         break;
326                                 case 0xe044:
327                                         /* NIC Link is Down */
328                                         pr_debug("NIC Link is Down\n");
329                                         break;
330                                 case 0xe045:
331                                         /* Unknown event but defined in DSDT */
332                                 default:
333                                         /* Unknown event */
334                                         pr_info("Unknown WMI event type 0x00: "
335                                                 "0x%x\n", (int)buffer_entry[i]);
336                                         break;
337                                 }
338                         }
339                         break;
340                 case 0x10:
341                         /* Keys pressed */
342                         for (i = 2; i < len; ++i)
343                                 dell_wmi_process_key(buffer_entry[i]);
344                         break;
345                 case 0x11:
346                         for (i = 2; i < len; ++i) {
347                                 switch (buffer_entry[i]) {
348                                 case 0xfff0:
349                                         /* Battery unplugged */
350                                         pr_debug("Battery unplugged\n");
351                                         break;
352                                 case 0xfff1:
353                                         /* Battery inserted */
354                                         pr_debug("Battery inserted\n");
355                                         break;
356                                 case 0x01e1:
357                                 case 0x02ea:
358                                 case 0x02eb:
359                                 case 0x02ec:
360                                 case 0x02f6:
361                                         /* Keyboard backlight level changed */
362                                         pr_debug("Keyboard backlight level "
363                                                  "changed\n");
364                                         break;
365                                 default:
366                                         /* Unknown event */
367                                         pr_info("Unknown WMI event type 0x11: "
368                                                 "0x%x\n", (int)buffer_entry[i]);
369                                         break;
370                                 }
371                         }
372                         break;
373                 default:
374                         /* Unknown event */
375                         pr_info("Unknown WMI event type 0x%x\n",
376                                 (int)buffer_entry[1]);
377                         break;
378                 }
379
380                 buffer_entry += len;
381
382         }
383
384         kfree(obj);
385 }
386
387 static bool have_scancode(u32 scancode, const struct key_entry *keymap, int len)
388 {
389         int i;
390
391         for (i = 0; i < len; i++)
392                 if (keymap[i].code == scancode)
393                         return true;
394
395         return false;
396 }
397
398 static void __init handle_dmi_entry(const struct dmi_header *dm,
399
400                                     void *opaque)
401
402 {
403         struct dell_dmi_results *results = opaque;
404         struct dell_bios_hotkey_table *table;
405         int hotkey_num, i, pos = 0;
406         struct key_entry *keymap;
407         int num_bios_keys;
408
409         if (results->err || results->keymap)
410                 return;         /* We already found the hotkey table. */
411
412         if (dm->type != 0xb2)
413                 return;
414
415         table = container_of(dm, struct dell_bios_hotkey_table, header);
416
417         hotkey_num = (table->header.length -
418                       sizeof(struct dell_bios_hotkey_table)) /
419                                 sizeof(struct dell_bios_keymap_entry);
420         if (hotkey_num < 1) {
421                 /*
422                  * Historically, dell-wmi would ignore a DMI entry of
423                  * fewer than 7 bytes.  Sizes between 4 and 8 bytes are
424                  * nonsensical (both the header and all entries are 4
425                  * bytes), so we approximate the old behavior by
426                  * ignoring tables with fewer than one entry.
427                  */
428                 return;
429         }
430
431         keymap = kcalloc(hotkey_num + ARRAY_SIZE(dell_wmi_extra_keymap) + 1,
432                          sizeof(struct key_entry), GFP_KERNEL);
433         if (!keymap) {
434                 results->err = -ENOMEM;
435                 return;
436         }
437
438         for (i = 0; i < hotkey_num; i++) {
439                 const struct dell_bios_keymap_entry *bios_entry =
440                                         &table->keymap[i];
441
442                 /* Uninitialized entries are 0 aka KEY_RESERVED. */
443                 u16 keycode = (bios_entry->keycode <
444                                ARRAY_SIZE(bios_to_linux_keycode)) ?
445                         bios_to_linux_keycode[bios_entry->keycode] :
446                         KEY_RESERVED;
447
448                 /*
449                  * Log if we find an entry in the DMI table that we don't
450                  * understand.  If this happens, we should figure out what
451                  * the entry means and add it to bios_to_linux_keycode.
452                  */
453                 if (keycode == KEY_RESERVED) {
454                         pr_info("firmware scancode 0x%x maps to unrecognized keycode 0x%x\n",
455                                 bios_entry->scancode, bios_entry->keycode);
456                         continue;
457                 }
458
459                 if (keycode == KEY_KBDILLUMTOGGLE)
460                         keymap[pos].type = KE_IGNORE;
461                 else
462                         keymap[pos].type = KE_KEY;
463                 keymap[pos].code = bios_entry->scancode;
464                 keymap[pos].keycode = keycode;
465
466                 pos++;
467         }
468
469         num_bios_keys = pos;
470
471         for (i = 0; i < ARRAY_SIZE(dell_wmi_extra_keymap); i++) {
472                 const struct key_entry *entry = &dell_wmi_extra_keymap[i];
473
474                 /*
475                  * Check if we've already found this scancode.  This takes
476                  * quadratic time, but it doesn't matter unless the list
477                  * of extra keys gets very long.
478                  */
479                 if (!have_scancode(entry->code, keymap, num_bios_keys)) {
480                         keymap[pos] = *entry;
481                         pos++;
482                 }
483         }
484
485         keymap[pos].type = KE_END;
486
487         results->keymap = keymap;
488 }
489
490 static int __init dell_wmi_input_setup(void)
491 {
492         struct dell_dmi_results dmi_results = {};
493         int err;
494
495         dell_wmi_input_dev = input_allocate_device();
496         if (!dell_wmi_input_dev)
497                 return -ENOMEM;
498
499         dell_wmi_input_dev->name = "Dell WMI hotkeys";
500         dell_wmi_input_dev->phys = "wmi/input0";
501         dell_wmi_input_dev->id.bustype = BUS_HOST;
502
503         if (dmi_walk(handle_dmi_entry, &dmi_results)) {
504                 /*
505                  * Historically, dell-wmi ignored dmi_walk errors.  A failure
506                  * is certainly surprising, but it probably just indicates
507                  * a very old laptop.
508                  */
509                 pr_warn("no DMI; using the old-style hotkey interface\n");
510         }
511
512         if (dmi_results.err) {
513                 err = dmi_results.err;
514                 goto err_free_dev;
515         }
516
517         if (dmi_results.keymap) {
518                 dell_new_hk_type = true;
519
520                 err = sparse_keymap_setup(dell_wmi_input_dev,
521                                           dmi_results.keymap, NULL);
522
523                 /*
524                  * Sparse keymap library makes a copy of keymap so we
525                  * don't need the original one that was allocated.
526                  */
527                 kfree(dmi_results.keymap);
528         } else {
529                 err = sparse_keymap_setup(dell_wmi_input_dev,
530                                           dell_wmi_legacy_keymap, NULL);
531         }
532         if (err)
533                 goto err_free_dev;
534
535         err = input_register_device(dell_wmi_input_dev);
536         if (err)
537                 goto err_free_keymap;
538
539         return 0;
540
541  err_free_keymap:
542         sparse_keymap_free(dell_wmi_input_dev);
543  err_free_dev:
544         input_free_device(dell_wmi_input_dev);
545         return err;
546 }
547
548 static void dell_wmi_input_destroy(void)
549 {
550         sparse_keymap_free(dell_wmi_input_dev);
551         input_unregister_device(dell_wmi_input_dev);
552 }
553
554 /*
555  * Descriptor buffer is 128 byte long and contains:
556  *
557  *       Name             Offset  Length  Value
558  * Vendor Signature          0       4    "DELL"
559  * Object Signature          4       4    " WMI"
560  * WMI Interface Version     8       4    <version>
561  * WMI buffer length        12       4    4096
562  */
563 static int __init dell_wmi_check_descriptor_buffer(void)
564 {
565         struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
566         union acpi_object *obj;
567         acpi_status status;
568         u32 *buffer;
569
570         status = wmi_query_block(DELL_DESCRIPTOR_GUID, 0, &out);
571         if (ACPI_FAILURE(status)) {
572                 pr_err("Cannot read Dell descriptor buffer - %d\n", status);
573                 return status;
574         }
575
576         obj = (union acpi_object *)out.pointer;
577         if (!obj) {
578                 pr_err("Dell descriptor buffer is empty\n");
579                 return -EINVAL;
580         }
581
582         if (obj->type != ACPI_TYPE_BUFFER) {
583                 pr_err("Cannot read Dell descriptor buffer\n");
584                 kfree(obj);
585                 return -EINVAL;
586         }
587
588         if (obj->buffer.length != 128) {
589                 pr_err("Dell descriptor buffer has invalid length (%d)\n",
590                         obj->buffer.length);
591                 if (obj->buffer.length < 16) {
592                         kfree(obj);
593                         return -EINVAL;
594                 }
595         }
596
597         buffer = (u32 *)obj->buffer.pointer;
598
599         if (buffer[0] != 0x4C4C4544 && buffer[1] != 0x494D5720)
600                 pr_warn("Dell descriptor buffer has invalid signature (%*ph)\n",
601                         8, buffer);
602
603         if (buffer[2] != 0 && buffer[2] != 1)
604                 pr_warn("Dell descriptor buffer has unknown version (%d)\n",
605                         buffer[2]);
606
607         if (buffer[3] != 4096)
608                 pr_warn("Dell descriptor buffer has invalid buffer length (%d)\n",
609                         buffer[3]);
610
611         dell_wmi_interface_version = buffer[2];
612
613         pr_info("Detected Dell WMI interface version %u\n",
614                 dell_wmi_interface_version);
615
616         kfree(obj);
617         return 0;
618 }
619
620 /*
621  * According to Dell SMBIOS documentation:
622  *
623  * 17  3  Application Program Registration
624  *
625  *     cbArg1 Application ID 1 = 0x00010000
626  *     cbArg2 Application ID 2
627  *            QUICKSET/DCP = 0x51534554 "QSET"
628  *            ALS Driver   = 0x416c7353 "AlsS"
629  *            Latitude ON  = 0x4c6f6e52 "LonR"
630  *     cbArg3 Application version or revision number
631  *     cbArg4 0 = Unregister application
632  *            1 = Register application
633  *     cbRes1 Standard return codes (0, -1, -2)
634  */
635
636 static int dell_wmi_events_set_enabled(bool enable)
637 {
638         struct calling_interface_buffer *buffer;
639         int ret;
640
641         buffer = dell_smbios_get_buffer();
642         buffer->input[0] = 0x10000;
643         buffer->input[1] = 0x51534554;
644         buffer->input[3] = enable;
645         dell_smbios_send_request(17, 3);
646         ret = buffer->output[0];
647         dell_smbios_release_buffer();
648
649         return dell_smbios_error(ret);
650 }
651
652 static int __init dell_wmi_init(void)
653 {
654         int err;
655         acpi_status status;
656
657         if (!wmi_has_guid(DELL_EVENT_GUID) ||
658             !wmi_has_guid(DELL_DESCRIPTOR_GUID)) {
659                 pr_warn("Dell WMI GUID were not found\n");
660                 return -ENODEV;
661         }
662
663         err = dell_wmi_check_descriptor_buffer();
664         if (err)
665                 return err;
666
667         err = dell_wmi_input_setup();
668         if (err)
669                 return err;
670
671         status = wmi_install_notify_handler(DELL_EVENT_GUID,
672                                          dell_wmi_notify, NULL);
673         if (ACPI_FAILURE(status)) {
674                 dell_wmi_input_destroy();
675                 pr_err("Unable to register notify handler - %d\n", status);
676                 return -ENODEV;
677         }
678
679         dmi_check_system(dell_wmi_smbios_list);
680
681         if (wmi_requires_smbios_request) {
682                 err = dell_wmi_events_set_enabled(true);
683                 if (err) {
684                         pr_err("Failed to enable WMI events\n");
685                         wmi_remove_notify_handler(DELL_EVENT_GUID);
686                         dell_wmi_input_destroy();
687                         return err;
688                 }
689         }
690
691         return 0;
692 }
693 module_init(dell_wmi_init);
694
695 static void __exit dell_wmi_exit(void)
696 {
697         if (wmi_requires_smbios_request)
698                 dell_wmi_events_set_enabled(false);
699         wmi_remove_notify_handler(DELL_EVENT_GUID);
700         dell_wmi_input_destroy();
701 }
702 module_exit(dell_wmi_exit);