xref: /linux/drivers/acpi/event.c (revision 4bedea94545165364618d403d03b61d797acba0b)
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);
141