aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2009-12-16 02:21:25 -0500
committerLen Brown <len.brown@intel.com>2009-12-16 02:21:25 -0500
commitb6202832b43abb56b90ba8d68e2b9fc53c442fa6 (patch)
tree92036b22402fb1a5e50be94073e9475f8b2824ae /drivers/platform
parent1a544d28dd2fd7c90bb23118ab0ca09b1304a50c (diff)
parent1caab3c1a90be3aa4ec3599409d8fe044b077478 (diff)
Merge branch 'wmi' into release
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/wmi.c175
1 files changed, 173 insertions, 2 deletions
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index 177f8d767df4..e425a868cd3a 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -30,6 +30,7 @@
30#include <linux/kernel.h> 30#include <linux/kernel.h>
31#include <linux/init.h> 31#include <linux/init.h>
32#include <linux/types.h> 32#include <linux/types.h>
33#include <linux/device.h>
33#include <linux/list.h> 34#include <linux/list.h>
34#include <linux/acpi.h> 35#include <linux/acpi.h>
35#include <acpi/acpi_bus.h> 36#include <acpi/acpi_bus.h>
@@ -65,6 +66,7 @@ struct wmi_block {
65 acpi_handle handle; 66 acpi_handle handle;
66 wmi_notify_handler handler; 67 wmi_notify_handler handler;
67 void *handler_data; 68 void *handler_data;
69 struct device *dev;
68}; 70};
69 71
70static struct wmi_block wmi_blocks; 72static struct wmi_block wmi_blocks;
@@ -195,6 +197,34 @@ static bool wmi_parse_guid(const u8 *src, u8 *dest)
195 return true; 197 return true;
196} 198}
197 199
200/*
201 * Convert a raw GUID to the ACII string representation
202 */
203static int wmi_gtoa(const char *in, char *out)
204{
205 int i;
206
207 for (i = 3; i >= 0; i--)
208 out += sprintf(out, "%02X", in[i] & 0xFF);
209
210 out += sprintf(out, "-");
211 out += sprintf(out, "%02X", in[5] & 0xFF);
212 out += sprintf(out, "%02X", in[4] & 0xFF);
213 out += sprintf(out, "-");
214 out += sprintf(out, "%02X", in[7] & 0xFF);
215 out += sprintf(out, "%02X", in[6] & 0xFF);
216 out += sprintf(out, "-");
217 out += sprintf(out, "%02X", in[8] & 0xFF);
218 out += sprintf(out, "%02X", in[9] & 0xFF);
219 out += sprintf(out, "-");
220
221 for (i = 10; i <= 15; i++)
222 out += sprintf(out, "%02X", in[i] & 0xFF);
223
224 out = '\0';
225 return 0;
226}
227
198static bool find_guid(const char *guid_string, struct wmi_block **out) 228static bool find_guid(const char *guid_string, struct wmi_block **out)
199{ 229{
200 char tmp[16], guid_input[16]; 230 char tmp[16], guid_input[16];
@@ -555,6 +585,138 @@ bool wmi_has_guid(const char *guid_string)
555EXPORT_SYMBOL_GPL(wmi_has_guid); 585EXPORT_SYMBOL_GPL(wmi_has_guid);
556 586
557/* 587/*
588 * sysfs interface
589 */
590static ssize_t show_modalias(struct device *dev, struct device_attribute *attr,
591 char *buf)
592{
593 char guid_string[37];
594 struct wmi_block *wblock;
595
596 wblock = dev_get_drvdata(dev);
597 if (!wblock)
598 return -ENOMEM;
599
600 wmi_gtoa(wblock->gblock.guid, guid_string);
601
602 return sprintf(buf, "wmi:%s\n", guid_string);
603}
604static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
605
606static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
607{
608 char guid_string[37];
609
610 struct wmi_block *wblock;
611
612 if (add_uevent_var(env, "MODALIAS="))
613 return -ENOMEM;
614
615 wblock = dev_get_drvdata(dev);
616 if (!wblock)
617 return -ENOMEM;
618
619 wmi_gtoa(wblock->gblock.guid, guid_string);
620
621 strcpy(&env->buf[env->buflen - 1], "wmi:");
622 memcpy(&env->buf[env->buflen - 1 + 4], guid_string, 36);
623 env->buflen += 40;
624
625 return 0;
626}
627
628static void wmi_dev_free(struct device *dev)
629{
630 kfree(dev);
631}
632
633static struct class wmi_class = {
634 .name = "wmi",
635 .dev_release = wmi_dev_free,
636 .dev_uevent = wmi_dev_uevent,
637};
638
639static int wmi_create_devs(void)
640{
641 int result;
642 char guid_string[37];
643 struct guid_block *gblock;
644 struct wmi_block *wblock;
645 struct list_head *p;
646 struct device *guid_dev;
647
648 /* Create devices for all the GUIDs */
649 list_for_each(p, &wmi_blocks.list) {
650 wblock = list_entry(p, struct wmi_block, list);
651
652 guid_dev = kzalloc(sizeof(struct device), GFP_KERNEL);
653 if (!guid_dev)
654 return -ENOMEM;
655
656 wblock->dev = guid_dev;
657
658 guid_dev->class = &wmi_class;
659 dev_set_drvdata(guid_dev, wblock);
660
661 gblock = &wblock->gblock;
662
663 wmi_gtoa(gblock->guid, guid_string);
664 dev_set_name(guid_dev, guid_string);
665
666 result = device_register(guid_dev);
667 if (result)
668 return result;
669
670 result = device_create_file(guid_dev, &dev_attr_modalias);
671 if (result)
672 return result;
673 }
674
675 return 0;
676}
677
678static void wmi_remove_devs(void)
679{
680 struct guid_block *gblock;
681 struct wmi_block *wblock;
682 struct list_head *p;
683 struct device *guid_dev;
684
685 /* Delete devices for all the GUIDs */
686 list_for_each(p, &wmi_blocks.list) {
687 wblock = list_entry(p, struct wmi_block, list);
688
689 guid_dev = wblock->dev;
690 gblock = &wblock->gblock;
691
692 device_remove_file(guid_dev, &dev_attr_modalias);
693
694 device_unregister(guid_dev);
695 }
696}
697
698static void wmi_class_exit(void)
699{
700 wmi_remove_devs();
701 class_unregister(&wmi_class);
702}
703
704static int wmi_class_init(void)
705{
706 int ret;
707
708 ret = class_register(&wmi_class);
709 if (ret)
710 return ret;
711
712 ret = wmi_create_devs();
713 if (ret)
714 wmi_class_exit();
715
716 return ret;
717}
718
719/*
558 * Parse the _WDG method for the GUID data blocks 720 * Parse the _WDG method for the GUID data blocks
559 */ 721 */
560static __init acpi_status parse_wdg(acpi_handle handle) 722static __init acpi_status parse_wdg(acpi_handle handle)
@@ -709,10 +871,17 @@ static int __init acpi_wmi_init(void)
709 871
710 if (result < 0) { 872 if (result < 0) {
711 printk(KERN_INFO PREFIX "Error loading mapper\n"); 873 printk(KERN_INFO PREFIX "Error loading mapper\n");
712 } else { 874 return -ENODEV;
713 printk(KERN_INFO PREFIX "Mapper loaded\n"); 875 }
876
877 result = wmi_class_init();
878 if (result) {
879 acpi_bus_unregister_driver(&acpi_wmi_driver);
880 return result;
714 } 881 }
715 882
883 printk(KERN_INFO PREFIX "Mapper loaded\n");
884
716 return result; 885 return result;
717} 886}
718 887
@@ -721,6 +890,8 @@ static void __exit acpi_wmi_exit(void)
721 struct list_head *p, *tmp; 890 struct list_head *p, *tmp;
722 struct wmi_block *wblock; 891 struct wmi_block *wblock;
723 892
893 wmi_class_exit();
894
724 acpi_bus_unregister_driver(&acpi_wmi_driver); 895 acpi_bus_unregister_driver(&acpi_wmi_driver);
725 896
726 list_for_each_safe(p, tmp, &wmi_blocks.list) { 897 list_for_each_safe(p, tmp, &wmi_blocks.list) {