30 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
32 #include <linux/kernel.h>
34 #include <linux/types.h>
35 #include <linux/device.h>
36 #include <linux/list.h>
38 #include <linux/slab.h>
39 #include <linux/module.h>
48 #define ACPI_WMI_CLASS "wmi"
80 #define ACPI_WMI_EXPENSIVE 0x1
81 #define ACPI_WMI_METHOD 0x2
82 #define ACPI_WMI_STRING 0x4
83 #define ACPI_WMI_EVENT 0x8
85 static bool debug_event;
88 "Log WMI Events [0/1]");
90 static bool debug_dump_wdg;
93 "Dump available WMI interfaces [0/1]");
95 static int acpi_wmi_remove(
struct acpi_device *
device,
int type);
96 static int acpi_wmi_add(
struct acpi_device *
device);
97 static void acpi_wmi_notify(
struct acpi_device *
device,
u32 event);
106 static struct acpi_driver acpi_wmi_driver = {
109 .ids = wmi_device_ids,
112 .remove = acpi_wmi_remove,
113 .notify = acpi_wmi_notify,
130 static int wmi_parse_hexbyte(
const u8 *
src)
143 return (h << 4) |
value;
154 static void wmi_swap_bytes(
u8 *src,
u8 *
dest)
158 for (i = 0; i <= 3; i++)
159 memcpy(dest + i, src + (3 - i), 1);
161 for (i = 0; i <= 1; i++)
162 memcpy(dest + 4 + i, src + (5 - i), 1);
164 for (i = 0; i <= 1; i++)
165 memcpy(dest + 6 + i, src + (7 - i), 1);
167 memcpy(dest + 8, src + 8, 8);
180 static bool wmi_parse_guid(
const u8 *src,
u8 *dest)
182 static const int size[] = { 4, 2, 2, 2, 6 };
185 if (src[8] !=
'-' || src[13] !=
'-' ||
186 src[18] !=
'-' || src[23] !=
'-')
189 for (j = 0; j < 5; j++, src++) {
190 for (i = 0; i < size[
j]; i++, src += 2, *dest++ =
v) {
191 v = wmi_parse_hexbyte(src);
203 static int wmi_gtoa(
const char *
in,
char *
out)
207 for (i = 3; i >= 0; i--)
208 out +=
sprintf(out,
"%02X", in[i] & 0xFF);
211 out +=
sprintf(out,
"%02X", in[5] & 0xFF);
212 out +=
sprintf(out,
"%02X", in[4] & 0xFF);
214 out +=
sprintf(out,
"%02X", in[7] & 0xFF);
215 out +=
sprintf(out,
"%02X", in[6] & 0xFF);
217 out +=
sprintf(out,
"%02X", in[8] & 0xFF);
218 out +=
sprintf(out,
"%02X", in[9] & 0xFF);
221 for (i = 10; i <= 15; i++)
222 out +=
sprintf(out,
"%02X", in[i] & 0xFF);
228 static bool find_guid(
const char *guid_string,
struct wmi_block **out)
230 char tmp[16], guid_input[16];
235 wmi_parse_guid(guid_string, tmp);
236 wmi_swap_bytes(tmp, guid_input);
242 if (
memcmp(block->
guid, guid_input, 16) == 0) {
302 char method[5] =
"WM";
304 if (!find_guid(guid_string, &wblock))
319 params[0].
integer.value = instance;
321 params[1].
integer.value = method_id;
361 char wc_method[5] =
"WC";
363 if (!guid_string || !out)
366 if (!find_guid(guid_string, &wblock))
382 wq_params[0].
integer.value = instance;
392 wc_params[0].
integer.value = 1;
417 wc_params[0].
integer.value = 0;
419 wc_method, &wc_input,
NULL);
442 char method[5] =
"WS";
444 if (!guid_string || !in)
447 if (!find_guid(guid_string, &wblock))
463 params[0].
integer.value = instance;
479 static void wmi_dump_wdg(
const struct guid_block *g)
481 char guid_string[37];
483 wmi_gtoa(g->
guid, guid_string);
493 pr_cont(
" ACPI_WMI_EXPENSIVE");
505 static void wmi_notify_debug(
u32 value,
void *
context)
512 if (status !=
AE_OK) {
513 pr_info(
"bad event status 0x%x\n", status);
550 wmi_notify_handler handler,
void *
data)
554 char tmp[16], guid_input[16];
557 if (!guid || !handler)
560 wmi_parse_guid(guid, tmp);
561 wmi_swap_bytes(tmp, guid_input);
569 block->
handler != wmi_notify_debug)
575 wmi_status = wmi_method_enable(block, 1);
576 if ((wmi_status !=
AE_OK) ||
595 char tmp[16], guid_input[16];
601 wmi_parse_guid(guid, tmp);
602 wmi_swap_bytes(tmp, guid_input);
610 block->
handler == wmi_notify_debug)
614 block->
handler = wmi_notify_debug;
617 wmi_status = wmi_method_enable(block, 0);
620 if ((wmi_status !=
AE_OK) ||
621 ((wmi_status ==
AE_OK) &&
675 return find_guid(guid_string,
NULL);
685 char guid_string[37];
692 wmi_gtoa(wblock->
gblock.guid, guid_string);
694 return sprintf(buf,
"wmi:%s\n", guid_string);
704 char guid_string[37];
715 wmi_gtoa(wblock->
gblock.guid, guid_string);
724 static void wmi_dev_free(
struct device *dev)
731 static struct class wmi_class = {
733 .dev_release = wmi_dev_free,
734 .dev_uevent = wmi_dev_uevent,
735 .dev_attrs = wmi_dev_attrs,
738 static int wmi_create_device(
const struct guid_block *gblock,
741 char guid_string[37];
743 wblock->
dev.class = &wmi_class;
745 wmi_gtoa(gblock->
guid, guid_string);
753 static void wmi_free_devices(
void)
760 if (wblock->
dev.class)
767 static bool guid_already_parsed(
const char *guid_string)
801 goto out_free_pointer;
807 for (i = 0; i < total; i++) {
809 wmi_dump_wdg(&gblock[i]);
824 if (!guid_already_parsed(gblock[i].guid)) {
825 retval = wmi_create_device(&gblock[i], wblock, handle);
828 goto out_free_pointer;
835 wblock->
handler = wmi_notify_debug;
836 wmi_method_enable(wblock, 1);
853 acpi_wmi_ec_space_handler(
u32 function, acpi_physical_address
address,
855 void *handler_context,
void *region_context)
860 if ((address > 0xFF) || !value)
870 result =
ec_read(address, &temp);
871 (*value) |= ((
u64)temp) <<
i;
873 temp = 0xff & ((*value) >>
i);
892 static void acpi_wmi_notify(
struct acpi_device *
device,
u32 event)
897 char guid_string[37];
908 wmi_gtoa(wblock->
gblock.guid, guid_string);
909 pr_info(
"DEBUG Event GUID: %s\n", guid_string);
913 device->pnp.device_class, dev_name(&device->dev),
920 static int acpi_wmi_remove(
struct acpi_device *device,
int type)
929 static int acpi_wmi_add(
struct acpi_device *device)
936 &acpi_wmi_ec_space_handler,
939 pr_err(
"Error installing EC region handler\n");
943 error = parse_wdg(device->handle);
947 &acpi_wmi_ec_space_handler);
948 pr_err(
"Failed to parse WDG method\n");
955 static int __init acpi_wmi_init(
void)
968 pr_err(
"Error loading mapper\n");
977 static void __exit acpi_wmi_exit(
void)