event.c revision 4be44fcd3bf648b782f4460fd06dfae6c42ded4b
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * event.c - exporting ACPI events via procfs
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h>
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/proc_fs.h>
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/poll.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <acpi/acpi_drivers.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define _COMPONENT		ACPI_SYSTEM_COMPONENT
164be44fcd3bf648b782f4460fd06dfae6c42ded4bLen BrownACPI_MODULE_NAME("event")
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Global vars for handling event proc entry */
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEFINE_SPINLOCK(acpi_system_event_lock);
204be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownint event_is_open = 0;
214be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownextern struct list_head acpi_bus_event_list;
224be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownextern wait_queue_head_t acpi_bus_event_queue;
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
244be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_system_open_event(struct inode *inode, struct file *file)
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
26c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek	spin_lock_irq(&acpi_system_event_lock);
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek	if (event_is_open)
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_busy;
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	event_is_open = 1;
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek	spin_unlock_irq(&acpi_system_event_lock);
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
364be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown      out_busy:
37c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek	spin_unlock_irq(&acpi_system_event_lock);
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -EBUSY;
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
424be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownacpi_system_read_event(struct file *file, char __user * buffer, size_t count,
434be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		       loff_t * ppos)
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
454be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	int result = 0;
464be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	struct acpi_bus_event event;
474be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	static char str[ACPI_MAX_STRING];
484be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	static int chars_remaining = 0;
494be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	static char *ptr;
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ACPI_FUNCTION_TRACE("acpi_system_read_event");
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!chars_remaining) {
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memset(&event, 0, sizeof(struct acpi_bus_event));
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((file->f_flags & O_NONBLOCK)
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    && (list_empty(&acpi_bus_event_list)))
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return_VALUE(-EAGAIN);
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		result = acpi_bus_receive_event(&event);
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (result) {
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return_VALUE(-EIO);
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
654be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		chars_remaining = sprintf(str, "%s %s %08x %08x\n",
664be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					  event.device_class ? event.
674be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					  device_class : "<unknown>",
684be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					  event.bus_id ? event.
694be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					  bus_id : "<unknown>", event.type,
704be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					  event.data);
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ptr = str;
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chars_remaining < count) {
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count = chars_remaining;
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (copy_to_user(buffer, ptr, count))
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return_VALUE(-EFAULT);
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*ppos += count;
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	chars_remaining -= count;
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ptr += count;
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return_VALUE(count);
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
884be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_system_close_event(struct inode *inode, struct file *file)
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
904be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	spin_lock_irq(&acpi_system_event_lock);
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	event_is_open = 0;
924be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	spin_unlock_irq(&acpi_system_event_lock);
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
964be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic unsigned int acpi_system_poll_event(struct file *file, poll_table * wait)
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	poll_wait(file, &acpi_bus_event_queue, wait);
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!list_empty(&acpi_bus_event_list))
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return POLLIN | POLLRDNORM;
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct file_operations acpi_system_event_ops = {
1054be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	.open = acpi_system_open_event,
1064be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	.read = acpi_system_read_event,
1074be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	.release = acpi_system_close_event,
1084be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	.poll = acpi_system_poll_event,
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init acpi_event_init(void)
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1134be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	struct proc_dir_entry *entry;
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error = 0;
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ACPI_FUNCTION_TRACE("acpi_event_init");
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (acpi_disabled)
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return_VALUE(0);
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* 'event' [R] */
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	entry = create_proc_entry("event", S_IRUSR, acpi_root_dir);
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (entry)
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		entry->proc_fops = &acpi_system_event_ops;
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
1264be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1274be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				  "Unable to create '%s' proc fs entry\n",
1284be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				  "event"));
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		error = -EFAULT;
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return_VALUE(error);
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssubsys_initcall(acpi_event_init);
135