Commit b6202832 authored by Len Brown's avatar Len Brown

Merge branch 'wmi' into release

parents 1a544d28 1caab3c1
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/device.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <acpi/acpi_bus.h> #include <acpi/acpi_bus.h>
...@@ -65,6 +66,7 @@ struct wmi_block { ...@@ -65,6 +66,7 @@ struct wmi_block {
acpi_handle handle; acpi_handle handle;
wmi_notify_handler handler; wmi_notify_handler handler;
void *handler_data; void *handler_data;
struct device *dev;
}; };
static struct wmi_block wmi_blocks; static struct wmi_block wmi_blocks;
...@@ -195,6 +197,34 @@ static bool wmi_parse_guid(const u8 *src, u8 *dest) ...@@ -195,6 +197,34 @@ static bool wmi_parse_guid(const u8 *src, u8 *dest)
return true; return true;
} }
/*
* Convert a raw GUID to the ACII string representation
*/
static int wmi_gtoa(const char *in, char *out)
{
int i;
for (i = 3; i >= 0; i--)
out += sprintf(out, "%02X", in[i] & 0xFF);
out += sprintf(out, "-");
out += sprintf(out, "%02X", in[5] & 0xFF);
out += sprintf(out, "%02X", in[4] & 0xFF);
out += sprintf(out, "-");
out += sprintf(out, "%02X", in[7] & 0xFF);
out += sprintf(out, "%02X", in[6] & 0xFF);
out += sprintf(out, "-");
out += sprintf(out, "%02X", in[8] & 0xFF);
out += sprintf(out, "%02X", in[9] & 0xFF);
out += sprintf(out, "-");
for (i = 10; i <= 15; i++)
out += sprintf(out, "%02X", in[i] & 0xFF);
out = '\0';
return 0;
}
static bool find_guid(const char *guid_string, struct wmi_block **out) static bool find_guid(const char *guid_string, struct wmi_block **out)
{ {
char tmp[16], guid_input[16]; char tmp[16], guid_input[16];
...@@ -554,6 +584,138 @@ bool wmi_has_guid(const char *guid_string) ...@@ -554,6 +584,138 @@ bool wmi_has_guid(const char *guid_string)
} }
EXPORT_SYMBOL_GPL(wmi_has_guid); EXPORT_SYMBOL_GPL(wmi_has_guid);
/*
* sysfs interface
*/
static ssize_t show_modalias(struct device *dev, struct device_attribute *attr,
char *buf)
{
char guid_string[37];
struct wmi_block *wblock;
wblock = dev_get_drvdata(dev);
if (!wblock)
return -ENOMEM;
wmi_gtoa(wblock->gblock.guid, guid_string);
return sprintf(buf, "wmi:%s\n", guid_string);
}
static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
{
char guid_string[37];
struct wmi_block *wblock;
if (add_uevent_var(env, "MODALIAS="))
return -ENOMEM;
wblock = dev_get_drvdata(dev);
if (!wblock)
return -ENOMEM;
wmi_gtoa(wblock->gblock.guid, guid_string);
strcpy(&env->buf[env->buflen - 1], "wmi:");
memcpy(&env->buf[env->buflen - 1 + 4], guid_string, 36);
env->buflen += 40;
return 0;
}
static void wmi_dev_free(struct device *dev)
{
kfree(dev);
}
static struct class wmi_class = {
.name = "wmi",
.dev_release = wmi_dev_free,
.dev_uevent = wmi_dev_uevent,
};
static int wmi_create_devs(void)
{
int result;
char guid_string[37];
struct guid_block *gblock;
struct wmi_block *wblock;
struct list_head *p;
struct device *guid_dev;
/* Create devices for all the GUIDs */
list_for_each(p, &wmi_blocks.list) {
wblock = list_entry(p, struct wmi_block, list);
guid_dev = kzalloc(sizeof(struct device), GFP_KERNEL);
if (!guid_dev)
return -ENOMEM;
wblock->dev = guid_dev;
guid_dev->class = &wmi_class;
dev_set_drvdata(guid_dev, wblock);
gblock = &wblock->gblock;
wmi_gtoa(gblock->guid, guid_string);
dev_set_name(guid_dev, guid_string);
result = device_register(guid_dev);
if (result)
return result;
result = device_create_file(guid_dev, &dev_attr_modalias);
if (result)
return result;
}
return 0;
}
static void wmi_remove_devs(void)
{
struct guid_block *gblock;
struct wmi_block *wblock;
struct list_head *p;
struct device *guid_dev;
/* Delete devices for all the GUIDs */
list_for_each(p, &wmi_blocks.list) {
wblock = list_entry(p, struct wmi_block, list);
guid_dev = wblock->dev;
gblock = &wblock->gblock;
device_remove_file(guid_dev, &dev_attr_modalias);
device_unregister(guid_dev);
}
}
static void wmi_class_exit(void)
{
wmi_remove_devs();
class_unregister(&wmi_class);
}
static int wmi_class_init(void)
{
int ret;
ret = class_register(&wmi_class);
if (ret)
return ret;
ret = wmi_create_devs();
if (ret)
wmi_class_exit();
return ret;
}
/* /*
* Parse the _WDG method for the GUID data blocks * Parse the _WDG method for the GUID data blocks
*/ */
...@@ -709,10 +871,17 @@ static int __init acpi_wmi_init(void) ...@@ -709,10 +871,17 @@ static int __init acpi_wmi_init(void)
if (result < 0) { if (result < 0) {
printk(KERN_INFO PREFIX "Error loading mapper\n"); printk(KERN_INFO PREFIX "Error loading mapper\n");
} else { return -ENODEV;
printk(KERN_INFO PREFIX "Mapper loaded\n");
} }
result = wmi_class_init();
if (result) {
acpi_bus_unregister_driver(&acpi_wmi_driver);
return result;
}
printk(KERN_INFO PREFIX "Mapper loaded\n");
return result; return result;
} }
...@@ -721,6 +890,8 @@ static void __exit acpi_wmi_exit(void) ...@@ -721,6 +890,8 @@ static void __exit acpi_wmi_exit(void)
struct list_head *p, *tmp; struct list_head *p, *tmp;
struct wmi_block *wblock; struct wmi_block *wblock;
wmi_class_exit();
acpi_bus_unregister_driver(&acpi_wmi_driver); acpi_bus_unregister_driver(&acpi_wmi_driver);
list_for_each_safe(p, tmp, &wmi_blocks.list) { list_for_each_safe(p, tmp, &wmi_blocks.list) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment