event.c revision f52fd66d2ea794010c2d7536cf8e6abed0ac4947
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 16f52fd66d2ea794010c2d7536cf8e6abed0ac4947Len 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 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!chars_remaining) { 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(&event, 0, sizeof(struct acpi_bus_event)); 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((file->f_flags & O_NONBLOCK) 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && (list_empty(&acpi_bus_event_list))) 57d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EAGAIN; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = acpi_bus_receive_event(&event); 605cc9eeef9a9567acdfc2f6943f24381bf460f008Pavel Machek if (result) 61d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return result; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 634be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown chars_remaining = sprintf(str, "%s %s %08x %08x\n", 644be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown event.device_class ? event. 654be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown device_class : "<unknown>", 664be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown event.bus_id ? event. 674be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown bus_id : "<unknown>", event.type, 684be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown event.data); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr = str; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chars_remaining < count) { 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = chars_remaining; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(buffer, ptr, count)) 77d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EFAULT; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *ppos += count; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chars_remaining -= count; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr += count; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 83d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return count; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 864be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_system_close_event(struct inode *inode, struct file *file) 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 884be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown spin_lock_irq(&acpi_system_event_lock); 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds event_is_open = 0; 904be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown spin_unlock_irq(&acpi_system_event_lock); 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 944be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic unsigned int acpi_system_poll_event(struct file *file, poll_table * wait) 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds poll_wait(file, &acpi_bus_event_queue, wait); 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!list_empty(&acpi_bus_event_list)) 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return POLLIN | POLLRDNORM; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 102d75080328affb4b268da430b7074cc8139cc662aArjan van de Venstatic const struct file_operations acpi_system_event_ops = { 1034be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .open = acpi_system_open_event, 1044be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .read = acpi_system_read_event, 1054be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .release = acpi_system_close_event, 1064be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .poll = acpi_system_poll_event, 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init acpi_event_init(void) 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1114be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct proc_dir_entry *entry; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error = 0; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (acpi_disabled) 116d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 'event' [R] */ 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = create_proc_entry("event", S_IRUSR, acpi_root_dir); 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (entry) 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry->proc_fops = &acpi_system_event_ops; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 123a6fc67202e0224e6c9d1d285cc0b444bce887ed5Thomas Renninger error = -ENODEV; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 125d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return error; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssubsys_initcall(acpi_event_init); 129