2 * ACPI-WMI mapping driver
4 * Copyright (C) 2007-2008 Carlos Corbacho <carlos@strangeworlds.co.uk>
6 * GUID parsing code from ldm.c is:
7 * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org>
8 * Copyright (c) 2001-2007 Anton Altaparmakov
9 * Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com>
11 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or (at
16 * your option) any later version.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
30 #include <linux/kernel.h>
31 #include <linux/init.h>
32 #include <linux/types.h>
33 #include <linux/device.h>
34 #include <linux/list.h>
35 #include <linux/acpi.h>
36 #include <linux/slab.h>
37 #include <acpi/acpi_bus.h>
38 #include <acpi/acpi_drivers.h>
40 ACPI_MODULE_NAME("wmi");
41 MODULE_AUTHOR("Carlos Corbacho");
42 MODULE_DESCRIPTION("ACPI-WMI Mapping Driver");
43 MODULE_LICENSE("GPL");
45 #define ACPI_WMI_CLASS "wmi"
47 #define PREFIX "ACPI: WMI: "
49 static DEFINE_MUTEX(wmi_data_lock
);
56 unsigned char notify_id
;
57 unsigned char reserved
;
65 struct list_head list
;
66 struct guid_block gblock
;
68 wmi_notify_handler handler
;
73 static struct wmi_block wmi_blocks
;
76 * If the GUID data block is marked as expensive, we must enable and
77 * explicitily disable data collection.
79 #define ACPI_WMI_EXPENSIVE 0x1
80 #define ACPI_WMI_METHOD 0x2 /* GUID is a method */
81 #define ACPI_WMI_STRING 0x4 /* GUID takes & returns a string */
82 #define ACPI_WMI_EVENT 0x8 /* GUID is an event */
84 static int debug_event
;
85 module_param(debug_event
, bool, 0444);
86 MODULE_PARM_DESC(debug_event
,
87 "Log WMI Events [0/1]");
89 static int debug_dump_wdg
;
90 module_param(debug_dump_wdg
, bool, 0444);
91 MODULE_PARM_DESC(debug_dump_wdg
,
92 "Dump available WMI interfaces [0/1]");
94 static int acpi_wmi_remove(struct acpi_device
*device
, int type
);
95 static int acpi_wmi_add(struct acpi_device
*device
);
96 static void acpi_wmi_notify(struct acpi_device
*device
, u32 event
);
98 static const struct acpi_device_id wmi_device_ids
[] = {
103 MODULE_DEVICE_TABLE(acpi
, wmi_device_ids
);
105 static struct acpi_driver acpi_wmi_driver
= {
107 .class = ACPI_WMI_CLASS
,
108 .ids
= wmi_device_ids
,
111 .remove
= acpi_wmi_remove
,
112 .notify
= acpi_wmi_notify
,
117 * GUID parsing functions
121 * wmi_parse_hexbyte - Convert a ASCII hex number to a byte
122 * @src: Pointer to at least 2 characters to convert.
124 * Convert a two character ASCII hex string to a number.
126 * Return: 0-255 Success, the byte was parsed correctly
127 * -1 Error, an invalid character was supplied
129 static int wmi_parse_hexbyte(const u8
*src
)
135 h
= value
= hex_to_bin(src
[0]);
140 value
= hex_to_bin(src
[1]);
142 return (h
<< 4) | value
;
147 * wmi_swap_bytes - Rearrange GUID bytes to match GUID binary
148 * @src: Memory block holding binary GUID (16 bytes)
149 * @dest: Memory block to hold byte swapped binary GUID (16 bytes)
151 * Byte swap a binary GUID to match it's real GUID value
153 static void wmi_swap_bytes(u8
*src
, u8
*dest
)
157 for (i
= 0; i
<= 3; i
++)
158 memcpy(dest
+ i
, src
+ (3 - i
), 1);
160 for (i
= 0; i
<= 1; i
++)
161 memcpy(dest
+ 4 + i
, src
+ (5 - i
), 1);
163 for (i
= 0; i
<= 1; i
++)
164 memcpy(dest
+ 6 + i
, src
+ (7 - i
), 1);
166 memcpy(dest
+ 8, src
+ 8, 8);
170 * wmi_parse_guid - Convert GUID from ASCII to binary
171 * @src: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
172 * @dest: Memory block to hold binary GUID (16 bytes)
174 * N.B. The GUID need not be NULL terminated.
176 * Return: 'true' @dest contains binary GUID
177 * 'false' @dest contents are undefined
179 static bool wmi_parse_guid(const u8
*src
, u8
*dest
)
181 static const int size
[] = { 4, 2, 2, 2, 6 };
184 if (src
[8] != '-' || src
[13] != '-' ||
185 src
[18] != '-' || src
[23] != '-')
188 for (j
= 0; j
< 5; j
++, src
++) {
189 for (i
= 0; i
< size
[j
]; i
++, src
+= 2, *dest
++ = v
) {
190 v
= wmi_parse_hexbyte(src
);
200 * Convert a raw GUID to the ACII string representation
202 static int wmi_gtoa(const char *in
, char *out
)
206 for (i
= 3; i
>= 0; i
--)
207 out
+= sprintf(out
, "%02X", in
[i
] & 0xFF);
209 out
+= sprintf(out
, "-");
210 out
+= sprintf(out
, "%02X", in
[5] & 0xFF);
211 out
+= sprintf(out
, "%02X", in
[4] & 0xFF);
212 out
+= sprintf(out
, "-");
213 out
+= sprintf(out
, "%02X", in
[7] & 0xFF);
214 out
+= sprintf(out
, "%02X", in
[6] & 0xFF);
215 out
+= sprintf(out
, "-");
216 out
+= sprintf(out
, "%02X", in
[8] & 0xFF);
217 out
+= sprintf(out
, "%02X", in
[9] & 0xFF);
218 out
+= sprintf(out
, "-");
220 for (i
= 10; i
<= 15; i
++)
221 out
+= sprintf(out
, "%02X", in
[i
] & 0xFF);
227 static bool find_guid(const char *guid_string
, struct wmi_block
**out
)
229 char tmp
[16], guid_input
[16];
230 struct wmi_block
*wblock
;
231 struct guid_block
*block
;
234 wmi_parse_guid(guid_string
, tmp
);
235 wmi_swap_bytes(tmp
, guid_input
);
237 list_for_each(p
, &wmi_blocks
.list
) {
238 wblock
= list_entry(p
, struct wmi_block
, list
);
239 block
= &wblock
->gblock
;
241 if (memcmp(block
->guid
, guid_input
, 16) == 0) {
250 static acpi_status
wmi_method_enable(struct wmi_block
*wblock
, int enable
)
252 struct guid_block
*block
= NULL
;
254 struct acpi_object_list input
;
255 union acpi_object params
[1];
259 block
= &wblock
->gblock
;
260 handle
= wblock
->handle
;
266 input
.pointer
= params
;
267 params
[0].type
= ACPI_TYPE_INTEGER
;
268 params
[0].integer
.value
= enable
;
270 snprintf(method
, 5, "WE%02X", block
->notify_id
);
271 status
= acpi_evaluate_object(handle
, method
, &input
, NULL
);
273 if (status
!= AE_OK
&& status
!= AE_NOT_FOUND
)
280 * Exported WMI functions
283 * wmi_evaluate_method - Evaluate a WMI method
284 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
285 * @instance: Instance index
286 * @method_id: Method ID to call
287 * &in: Buffer containing input for the method call
288 * &out: Empty buffer to return the method results
290 * Call an ACPI-WMI method
292 acpi_status
wmi_evaluate_method(const char *guid_string
, u8 instance
,
293 u32 method_id
, const struct acpi_buffer
*in
, struct acpi_buffer
*out
)
295 struct guid_block
*block
= NULL
;
296 struct wmi_block
*wblock
= NULL
;
299 struct acpi_object_list input
;
300 union acpi_object params
[3];
301 char method
[5] = "WM";
303 if (!find_guid(guid_string
, &wblock
))
306 block
= &wblock
->gblock
;
307 handle
= wblock
->handle
;
309 if (!(block
->flags
& ACPI_WMI_METHOD
))
312 if (block
->instance_count
< instance
)
313 return AE_BAD_PARAMETER
;
316 input
.pointer
= params
;
317 params
[0].type
= ACPI_TYPE_INTEGER
;
318 params
[0].integer
.value
= instance
;
319 params
[1].type
= ACPI_TYPE_INTEGER
;
320 params
[1].integer
.value
= method_id
;
325 if (block
->flags
& ACPI_WMI_STRING
) {
326 params
[2].type
= ACPI_TYPE_STRING
;
328 params
[2].type
= ACPI_TYPE_BUFFER
;
330 params
[2].buffer
.length
= in
->length
;
331 params
[2].buffer
.pointer
= in
->pointer
;
334 strncat(method
, block
->object_id
, 2);
336 status
= acpi_evaluate_object(handle
, method
, &input
, out
);
340 EXPORT_SYMBOL_GPL(wmi_evaluate_method
);
343 * wmi_query_block - Return contents of a WMI block
344 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
345 * @instance: Instance index
346 * &out: Empty buffer to return the contents of the data block to
348 * Return the contents of an ACPI-WMI data block to a buffer
350 acpi_status
wmi_query_block(const char *guid_string
, u8 instance
,
351 struct acpi_buffer
*out
)
353 struct guid_block
*block
= NULL
;
354 struct wmi_block
*wblock
= NULL
;
355 acpi_handle handle
, wc_handle
;
356 acpi_status status
, wc_status
= AE_ERROR
;
357 struct acpi_object_list input
, wc_input
;
358 union acpi_object wc_params
[1], wq_params
[1];
360 char wc_method
[5] = "WC";
362 if (!guid_string
|| !out
)
363 return AE_BAD_PARAMETER
;
365 if (!find_guid(guid_string
, &wblock
))
368 block
= &wblock
->gblock
;
369 handle
= wblock
->handle
;
371 if (block
->instance_count
< instance
)
372 return AE_BAD_PARAMETER
;
374 /* Check GUID is a data block */
375 if (block
->flags
& (ACPI_WMI_EVENT
| ACPI_WMI_METHOD
))
379 input
.pointer
= wq_params
;
380 wq_params
[0].type
= ACPI_TYPE_INTEGER
;
381 wq_params
[0].integer
.value
= instance
;
384 * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method first to
387 if (block
->flags
& ACPI_WMI_EXPENSIVE
) {
389 wc_input
.pointer
= wc_params
;
390 wc_params
[0].type
= ACPI_TYPE_INTEGER
;
391 wc_params
[0].integer
.value
= 1;
393 strncat(wc_method
, block
->object_id
, 2);
396 * Some GUIDs break the specification by declaring themselves
397 * expensive, but have no corresponding WCxx method. So we
398 * should not fail if this happens.
400 wc_status
= acpi_get_handle(handle
, wc_method
, &wc_handle
);
401 if (ACPI_SUCCESS(wc_status
))
402 wc_status
= acpi_evaluate_object(handle
, wc_method
,
406 strcpy(method
, "WQ");
407 strncat(method
, block
->object_id
, 2);
409 status
= acpi_evaluate_object(handle
, method
, &input
, out
);
412 * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method, even if
413 * the WQxx method failed - we should disable collection anyway.
415 if ((block
->flags
& ACPI_WMI_EXPENSIVE
) && ACPI_SUCCESS(wc_status
)) {
416 wc_params
[0].integer
.value
= 0;
417 status
= acpi_evaluate_object(handle
,
418 wc_method
, &wc_input
, NULL
);
423 EXPORT_SYMBOL_GPL(wmi_query_block
);
426 * wmi_set_block - Write to a WMI block
427 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
428 * @instance: Instance index
429 * &in: Buffer containing new values for the data block
431 * Write the contents of the input buffer to an ACPI-WMI data block
433 acpi_status
wmi_set_block(const char *guid_string
, u8 instance
,
434 const struct acpi_buffer
*in
)
436 struct guid_block
*block
= NULL
;
437 struct wmi_block
*wblock
= NULL
;
439 struct acpi_object_list input
;
440 union acpi_object params
[2];
441 char method
[5] = "WS";
443 if (!guid_string
|| !in
)
446 if (!find_guid(guid_string
, &wblock
))
449 block
= &wblock
->gblock
;
450 handle
= wblock
->handle
;
452 if (block
->instance_count
< instance
)
453 return AE_BAD_PARAMETER
;
455 /* Check GUID is a data block */
456 if (block
->flags
& (ACPI_WMI_EVENT
| ACPI_WMI_METHOD
))
460 input
.pointer
= params
;
461 params
[0].type
= ACPI_TYPE_INTEGER
;
462 params
[0].integer
.value
= instance
;
464 if (block
->flags
& ACPI_WMI_STRING
) {
465 params
[1].type
= ACPI_TYPE_STRING
;
467 params
[1].type
= ACPI_TYPE_BUFFER
;
469 params
[1].buffer
.length
= in
->length
;
470 params
[1].buffer
.pointer
= in
->pointer
;
472 strncat(method
, block
->object_id
, 2);
474 return acpi_evaluate_object(handle
, method
, &input
, NULL
);
476 EXPORT_SYMBOL_GPL(wmi_set_block
);
478 static void wmi_dump_wdg(const struct guid_block
*g
)
480 char guid_string
[37];
482 wmi_gtoa(g
->guid
, guid_string
);
483 printk(KERN_INFO PREFIX
"%s:\n", guid_string
);
484 printk(KERN_INFO PREFIX
"\tobject_id: %c%c\n",
485 g
->object_id
[0], g
->object_id
[1]);
486 printk(KERN_INFO PREFIX
"\tnotify_id: %02X\n", g
->notify_id
);
487 printk(KERN_INFO PREFIX
"\treserved: %02X\n", g
->reserved
);
488 printk(KERN_INFO PREFIX
"\tinstance_count: %d\n", g
->instance_count
);
489 printk(KERN_INFO PREFIX
"\tflags: %#x", g
->flags
);
492 if (g
->flags
& ACPI_WMI_EXPENSIVE
)
493 printk("ACPI_WMI_EXPENSIVE ");
494 if (g
->flags
& ACPI_WMI_METHOD
)
495 printk("ACPI_WMI_METHOD ");
496 if (g
->flags
& ACPI_WMI_STRING
)
497 printk("ACPI_WMI_STRING ");
498 if (g
->flags
& ACPI_WMI_EVENT
)
499 printk("ACPI_WMI_EVENT ");
505 static void wmi_notify_debug(u32 value
, void *context
)
507 struct acpi_buffer response
= { ACPI_ALLOCATE_BUFFER
, NULL
};
508 union acpi_object
*obj
;
511 status
= wmi_get_event_data(value
, &response
);
512 if (status
!= AE_OK
) {
513 printk(KERN_INFO
"wmi: bad event status 0x%x\n", status
);
517 obj
= (union acpi_object
*)response
.pointer
;
522 printk(KERN_INFO PREFIX
"DEBUG Event ");
524 case ACPI_TYPE_BUFFER
:
525 printk("BUFFER_TYPE - length %d\n", obj
->buffer
.length
);
527 case ACPI_TYPE_STRING
:
528 printk("STRING_TYPE - %s\n", obj
->string
.pointer
);
530 case ACPI_TYPE_INTEGER
:
531 printk("INTEGER_TYPE - %llu\n", obj
->integer
.value
);
533 case ACPI_TYPE_PACKAGE
:
534 printk("PACKAGE_TYPE - %d elements\n", obj
->package
.count
);
537 printk("object type 0x%X\n", obj
->type
);
543 * wmi_install_notify_handler - Register handler for WMI events
544 * @handler: Function to handle notifications
545 * @data: Data to be returned to handler when event is fired
547 * Register a handler for events sent to the ACPI-WMI mapper device.
549 acpi_status
wmi_install_notify_handler(const char *guid
,
550 wmi_notify_handler handler
, void *data
)
552 struct wmi_block
*block
;
555 if (!guid
|| !handler
)
556 return AE_BAD_PARAMETER
;
558 if (!find_guid(guid
, &block
))
561 if (block
->handler
&& block
->handler
!= wmi_notify_debug
)
562 return AE_ALREADY_ACQUIRED
;
564 block
->handler
= handler
;
565 block
->handler_data
= data
;
567 status
= wmi_method_enable(block
, 1);
571 EXPORT_SYMBOL_GPL(wmi_install_notify_handler
);
574 * wmi_uninstall_notify_handler - Unregister handler for WMI events
576 * Unregister handler for events sent to the ACPI-WMI mapper device.
578 acpi_status
wmi_remove_notify_handler(const char *guid
)
580 struct wmi_block
*block
;
581 acpi_status status
= AE_OK
;
584 return AE_BAD_PARAMETER
;
586 if (!find_guid(guid
, &block
))
589 if (!block
->handler
|| block
->handler
== wmi_notify_debug
)
590 return AE_NULL_ENTRY
;
593 block
->handler
= wmi_notify_debug
;
595 status
= wmi_method_enable(block
, 0);
596 block
->handler
= NULL
;
597 block
->handler_data
= NULL
;
601 EXPORT_SYMBOL_GPL(wmi_remove_notify_handler
);
604 * wmi_get_event_data - Get WMI data associated with an event
606 * @event: Event to find
607 * @out: Buffer to hold event data. out->pointer should be freed with kfree()
609 * Returns extra data associated with an event in WMI.
611 acpi_status
wmi_get_event_data(u32 event
, struct acpi_buffer
*out
)
613 struct acpi_object_list input
;
614 union acpi_object params
[1];
615 struct guid_block
*gblock
;
616 struct wmi_block
*wblock
;
620 input
.pointer
= params
;
621 params
[0].type
= ACPI_TYPE_INTEGER
;
622 params
[0].integer
.value
= event
;
624 list_for_each(p
, &wmi_blocks
.list
) {
625 wblock
= list_entry(p
, struct wmi_block
, list
);
626 gblock
= &wblock
->gblock
;
628 if ((gblock
->flags
& ACPI_WMI_EVENT
) &&
629 (gblock
->notify_id
== event
))
630 return acpi_evaluate_object(wblock
->handle
, "_WED",
636 EXPORT_SYMBOL_GPL(wmi_get_event_data
);
639 * wmi_has_guid - Check if a GUID is available
640 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
642 * Check if a given GUID is defined by _WDG
644 bool wmi_has_guid(const char *guid_string
)
646 return find_guid(guid_string
, NULL
);
648 EXPORT_SYMBOL_GPL(wmi_has_guid
);
653 static ssize_t
show_modalias(struct device
*dev
, struct device_attribute
*attr
,
656 char guid_string
[37];
657 struct wmi_block
*wblock
;
659 wblock
= dev_get_drvdata(dev
);
663 wmi_gtoa(wblock
->gblock
.guid
, guid_string
);
665 return sprintf(buf
, "wmi:%s\n", guid_string
);
667 static DEVICE_ATTR(modalias
, S_IRUGO
, show_modalias
, NULL
);
669 static int wmi_dev_uevent(struct device
*dev
, struct kobj_uevent_env
*env
)
671 char guid_string
[37];
673 struct wmi_block
*wblock
;
675 if (add_uevent_var(env
, "MODALIAS="))
678 wblock
= dev_get_drvdata(dev
);
682 wmi_gtoa(wblock
->gblock
.guid
, guid_string
);
684 strcpy(&env
->buf
[env
->buflen
- 1], "wmi:");
685 memcpy(&env
->buf
[env
->buflen
- 1 + 4], guid_string
, 36);
691 static void wmi_dev_free(struct device
*dev
)
696 static struct class wmi_class
= {
698 .dev_release
= wmi_dev_free
,
699 .dev_uevent
= wmi_dev_uevent
,
702 static int wmi_create_devs(void)
705 char guid_string
[37];
706 struct guid_block
*gblock
;
707 struct wmi_block
*wblock
;
709 struct device
*guid_dev
;
711 /* Create devices for all the GUIDs */
712 list_for_each(p
, &wmi_blocks
.list
) {
713 wblock
= list_entry(p
, struct wmi_block
, list
);
715 guid_dev
= kzalloc(sizeof(struct device
), GFP_KERNEL
);
719 wblock
->dev
= guid_dev
;
721 guid_dev
->class = &wmi_class
;
722 dev_set_drvdata(guid_dev
, wblock
);
724 gblock
= &wblock
->gblock
;
726 wmi_gtoa(gblock
->guid
, guid_string
);
727 dev_set_name(guid_dev
, guid_string
);
729 result
= device_register(guid_dev
);
733 result
= device_create_file(guid_dev
, &dev_attr_modalias
);
741 static void wmi_remove_devs(void)
743 struct guid_block
*gblock
;
744 struct wmi_block
*wblock
;
746 struct device
*guid_dev
;
748 /* Delete devices for all the GUIDs */
749 list_for_each(p
, &wmi_blocks
.list
) {
750 wblock
= list_entry(p
, struct wmi_block
, list
);
752 guid_dev
= wblock
->dev
;
753 gblock
= &wblock
->gblock
;
755 device_remove_file(guid_dev
, &dev_attr_modalias
);
757 device_unregister(guid_dev
);
761 static void wmi_class_exit(void)
764 class_unregister(&wmi_class
);
767 static int wmi_class_init(void)
771 ret
= class_register(&wmi_class
);
775 ret
= wmi_create_devs();
782 static bool guid_already_parsed(const char *guid_string
)
784 struct guid_block
*gblock
;
785 struct wmi_block
*wblock
;
788 list_for_each(p
, &wmi_blocks
.list
) {
789 wblock
= list_entry(p
, struct wmi_block
, list
);
790 gblock
= &wblock
->gblock
;
792 if (strncmp(gblock
->guid
, guid_string
, 16) == 0)
798 static void free_wmi_blocks(void)
800 struct wmi_block
*wblock
, *next
;
802 list_for_each_entry_safe(wblock
, next
, &wmi_blocks
.list
, list
) {
803 list_del(&wblock
->list
);
809 * Parse the _WDG method for the GUID data blocks
811 static acpi_status
parse_wdg(acpi_handle handle
)
813 struct acpi_buffer out
= {ACPI_ALLOCATE_BUFFER
, NULL
};
814 union acpi_object
*obj
;
815 const struct guid_block
*gblock
;
816 struct wmi_block
*wblock
;
817 char guid_string
[37];
821 status
= acpi_evaluate_object(handle
, "_WDG", NULL
, &out
);
823 if (ACPI_FAILURE(status
))
826 obj
= (union acpi_object
*) out
.pointer
;
830 if (obj
->type
!= ACPI_TYPE_BUFFER
) {
832 goto out_free_pointer
;
835 gblock
= (const struct guid_block
*)obj
->buffer
.pointer
;
836 total
= obj
->buffer
.length
/ sizeof(struct guid_block
);
838 for (i
= 0; i
< total
; i
++) {
840 Some WMI devices, like those for nVidia hooks, have a
841 duplicate GUID. It's not clear what we should do in this
842 case yet, so for now, we'll just ignore the duplicate.
843 Anyone who wants to add support for that device can come
844 up with a better workaround for the mess then.
846 if (guid_already_parsed(gblock
[i
].guid
) == true) {
847 wmi_gtoa(gblock
[i
].guid
, guid_string
);
848 printk(KERN_INFO PREFIX
"Skipping duplicate GUID %s\n",
853 wmi_dump_wdg(&gblock
[i
]);
855 wblock
= kzalloc(sizeof(struct wmi_block
), GFP_KERNEL
);
857 status
= AE_NO_MEMORY
;
858 goto out_free_pointer
;
861 wblock
->gblock
= gblock
[i
];
862 wblock
->handle
= handle
;
864 wblock
->handler
= wmi_notify_debug
;
865 wmi_method_enable(wblock
, 1);
867 list_add_tail(&wblock
->list
, &wmi_blocks
.list
);
873 if (ACPI_FAILURE(status
))
880 * WMI can have EmbeddedControl access regions. In which case, we just want to
881 * hand these off to the EC driver.
884 acpi_wmi_ec_space_handler(u32 function
, acpi_physical_address address
,
885 u32 bits
, u64
*value
,
886 void *handler_context
, void *region_context
)
888 int result
= 0, i
= 0;
891 if ((address
> 0xFF) || !value
)
892 return AE_BAD_PARAMETER
;
894 if (function
!= ACPI_READ
&& function
!= ACPI_WRITE
)
895 return AE_BAD_PARAMETER
;
898 return AE_BAD_PARAMETER
;
900 if (function
== ACPI_READ
) {
901 result
= ec_read(address
, &temp
);
902 (*value
) |= ((u64
)temp
) << i
;
904 temp
= 0xff & ((*value
) >> i
);
905 result
= ec_write(address
, temp
);
910 return AE_BAD_PARAMETER
;
923 static void acpi_wmi_notify(struct acpi_device
*device
, u32 event
)
925 struct guid_block
*block
;
926 struct wmi_block
*wblock
;
928 char guid_string
[37];
930 list_for_each(p
, &wmi_blocks
.list
) {
931 wblock
= list_entry(p
, struct wmi_block
, list
);
932 block
= &wblock
->gblock
;
934 if ((block
->flags
& ACPI_WMI_EVENT
) &&
935 (block
->notify_id
== event
)) {
937 wblock
->handler(event
, wblock
->handler_data
);
939 wmi_gtoa(wblock
->gblock
.guid
, guid_string
);
940 printk(KERN_INFO PREFIX
"DEBUG Event GUID:"
941 " %s\n", guid_string
);
944 acpi_bus_generate_netlink_event(
945 device
->pnp
.device_class
, dev_name(&device
->dev
),
952 static int acpi_wmi_remove(struct acpi_device
*device
, int type
)
954 acpi_remove_address_space_handler(device
->handle
,
955 ACPI_ADR_SPACE_EC
, &acpi_wmi_ec_space_handler
);
960 static int acpi_wmi_add(struct acpi_device
*device
)
965 status
= acpi_install_address_space_handler(device
->handle
,
967 &acpi_wmi_ec_space_handler
,
969 if (ACPI_FAILURE(status
)) {
970 printk(KERN_ERR PREFIX
"Error installing EC region handler\n");
974 status
= parse_wdg(device
->handle
);
975 if (ACPI_FAILURE(status
)) {
976 acpi_remove_address_space_handler(device
->handle
,
978 &acpi_wmi_ec_space_handler
);
979 printk(KERN_ERR PREFIX
"Failed to parse WDG method\n");
986 static int __init
acpi_wmi_init(void)
990 INIT_LIST_HEAD(&wmi_blocks
.list
);
995 result
= acpi_bus_register_driver(&acpi_wmi_driver
);
998 printk(KERN_INFO PREFIX
"Error loading mapper\n");
1002 result
= wmi_class_init();
1004 acpi_bus_unregister_driver(&acpi_wmi_driver
);
1008 printk(KERN_INFO PREFIX
"Mapper loaded\n");
1013 static void __exit
acpi_wmi_exit(void)
1017 acpi_bus_unregister_driver(&acpi_wmi_driver
);
1021 printk(KERN_INFO PREFIX
"Mapper unloaded\n");
1024 subsys_initcall(acpi_wmi_init
);
1025 module_exit(acpi_wmi_exit
);