diff options
Diffstat (limited to 'drivers/acpi/event.c')
-rw-r--r-- | drivers/acpi/event.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c new file mode 100644 index 000000000000..43c49f66a328 --- /dev/null +++ b/drivers/acpi/event.c | |||
@@ -0,0 +1,140 @@ | |||
1 | /* | ||
2 | * event.c - exporting ACPI events via procfs | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> | ||
5 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | #include <linux/spinlock.h> | ||
10 | #include <linux/proc_fs.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/poll.h> | ||
13 | #include <acpi/acpi_drivers.h> | ||
14 | |||
15 | #define _COMPONENT ACPI_SYSTEM_COMPONENT | ||
16 | ACPI_MODULE_NAME ("event") | ||
17 | |||
18 | /* Global vars for handling event proc entry */ | ||
19 | static DEFINE_SPINLOCK(acpi_system_event_lock); | ||
20 | int event_is_open = 0; | ||
21 | extern struct list_head acpi_bus_event_list; | ||
22 | extern wait_queue_head_t acpi_bus_event_queue; | ||
23 | |||
24 | static int | ||
25 | acpi_system_open_event(struct inode *inode, struct file *file) | ||
26 | { | ||
27 | spin_lock_irq (&acpi_system_event_lock); | ||
28 | |||
29 | if(event_is_open) | ||
30 | goto out_busy; | ||
31 | |||
32 | event_is_open = 1; | ||
33 | |||
34 | spin_unlock_irq (&acpi_system_event_lock); | ||
35 | return 0; | ||
36 | |||
37 | out_busy: | ||
38 | spin_unlock_irq (&acpi_system_event_lock); | ||
39 | return -EBUSY; | ||
40 | } | ||
41 | |||
42 | static ssize_t | ||
43 | acpi_system_read_event ( | ||
44 | struct file *file, | ||
45 | char __user *buffer, | ||
46 | size_t count, | ||
47 | loff_t *ppos) | ||
48 | { | ||
49 | int result = 0; | ||
50 | struct acpi_bus_event event; | ||
51 | static char str[ACPI_MAX_STRING]; | ||
52 | static int chars_remaining = 0; | ||
53 | static char *ptr; | ||
54 | |||
55 | |||
56 | ACPI_FUNCTION_TRACE("acpi_system_read_event"); | ||
57 | |||
58 | if (!chars_remaining) { | ||
59 | memset(&event, 0, sizeof(struct acpi_bus_event)); | ||
60 | |||
61 | if ((file->f_flags & O_NONBLOCK) | ||
62 | && (list_empty(&acpi_bus_event_list))) | ||
63 | return_VALUE(-EAGAIN); | ||
64 | |||
65 | result = acpi_bus_receive_event(&event); | ||
66 | if (result) { | ||
67 | return_VALUE(-EIO); | ||
68 | } | ||
69 | |||
70 | chars_remaining = sprintf(str, "%s %s %08x %08x\n", | ||
71 | event.device_class?event.device_class:"<unknown>", | ||
72 | event.bus_id?event.bus_id:"<unknown>", | ||
73 | event.type, event.data); | ||
74 | ptr = str; | ||
75 | } | ||
76 | |||
77 | if (chars_remaining < count) { | ||
78 | count = chars_remaining; | ||
79 | } | ||
80 | |||
81 | if (copy_to_user(buffer, ptr, count)) | ||
82 | return_VALUE(-EFAULT); | ||
83 | |||
84 | *ppos += count; | ||
85 | chars_remaining -= count; | ||
86 | ptr += count; | ||
87 | |||
88 | return_VALUE(count); | ||
89 | } | ||
90 | |||
91 | static int | ||
92 | acpi_system_close_event(struct inode *inode, struct file *file) | ||
93 | { | ||
94 | spin_lock_irq (&acpi_system_event_lock); | ||
95 | event_is_open = 0; | ||
96 | spin_unlock_irq (&acpi_system_event_lock); | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static unsigned int | ||
101 | acpi_system_poll_event( | ||
102 | struct file *file, | ||
103 | poll_table *wait) | ||
104 | { | ||
105 | poll_wait(file, &acpi_bus_event_queue, wait); | ||
106 | if (!list_empty(&acpi_bus_event_list)) | ||
107 | return POLLIN | POLLRDNORM; | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static struct file_operations acpi_system_event_ops = { | ||
112 | .open = acpi_system_open_event, | ||
113 | .read = acpi_system_read_event, | ||
114 | .release = acpi_system_close_event, | ||
115 | .poll = acpi_system_poll_event, | ||
116 | }; | ||
117 | |||
118 | static int __init acpi_event_init(void) | ||
119 | { | ||
120 | struct proc_dir_entry *entry; | ||
121 | int error = 0; | ||
122 | |||
123 | ACPI_FUNCTION_TRACE("acpi_event_init"); | ||
124 | |||
125 | if (acpi_disabled) | ||
126 | return_VALUE(0); | ||
127 | |||
128 | /* 'event' [R] */ | ||
129 | entry = create_proc_entry("event", S_IRUSR, acpi_root_dir); | ||
130 | if (entry) | ||
131 | entry->proc_fops = &acpi_system_event_ops; | ||
132 | else { | ||
133 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
134 | "Unable to create '%s' proc fs entry\n","event" )); | ||
135 | error = -EFAULT; | ||
136 | } | ||
137 | return_VALUE(error); | ||
138 | } | ||
139 | |||
140 | subsys_initcall(acpi_event_init); | ||