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 acpi_system_open_event(struct inode *inode, struct file *file) 25 { 26 spin_lock_irq(&acpi_system_event_lock); 27 28 if (event_is_open) 29 goto out_busy; 30 31 event_is_open = 1; 32 33 spin_unlock_irq(&acpi_system_event_lock); 34 return 0; 35 36 out_busy: 37 spin_unlock_irq(&acpi_system_event_lock); 38 return -EBUSY; 39 } 40 41 static ssize_t 42 acpi_system_read_event(struct file *file, char __user * buffer, size_t count, 43 loff_t * ppos) 44 { 45 int result = 0; 46 struct acpi_bus_event event; 47 static char str[ACPI_MAX_STRING]; 48 static int chars_remaining = 0; 49 static char *ptr; 50 51 ACPI_FUNCTION_TRACE("acpi_system_read_event"); 52 53 if (!chars_remaining) { 54 memset(&event, 0, sizeof(struct acpi_bus_event)); 55 56 if ((file->f_flags & O_NONBLOCK) 57 && (list_empty(&acpi_bus_event_list))) 58 return_VALUE(-EAGAIN); 59 60 result = acpi_bus_receive_event(&event); 61 if (result) { 62 return_VALUE(-EIO); 63 } 64 65 chars_remaining = sprintf(str, "%s %s %08x %08x\n", 66 event.device_class ? event. 67 device_class : "<unknown>", 68 event.bus_id ? event. 69 bus_id : "<unknown>", event.type, 70 event.data); 71 ptr = str; 72 } 73 74 if (chars_remaining < count) { 75 count = chars_remaining; 76 } 77 78 if (copy_to_user(buffer, ptr, count)) 79 return_VALUE(-EFAULT); 80 81 *ppos += count; 82 chars_remaining -= count; 83 ptr += count; 84 85 return_VALUE(count); 86 } 87 88 static int acpi_system_close_event(struct inode *inode, struct file *file) 89 { 90 spin_lock_irq(&acpi_system_event_lock); 91 event_is_open = 0; 92 spin_unlock_irq(&acpi_system_event_lock); 93 return 0; 94 } 95 96 static unsigned int acpi_system_poll_event(struct file *file, poll_table * wait) 97 { 98 poll_wait(file, &acpi_bus_event_queue, wait); 99 if (!list_empty(&acpi_bus_event_list)) 100 return POLLIN | POLLRDNORM; 101 return 0; 102 } 103 104 static struct file_operations acpi_system_event_ops = { 105 .open = acpi_system_open_event, 106 .read = acpi_system_read_event, 107 .release = acpi_system_close_event, 108 .poll = acpi_system_poll_event, 109 }; 110 111 static int __init acpi_event_init(void) 112 { 113 struct proc_dir_entry *entry; 114 int error = 0; 115 116 ACPI_FUNCTION_TRACE("acpi_event_init"); 117 118 if (acpi_disabled) 119 return_VALUE(0); 120 121 /* 'event' [R] */ 122 entry = create_proc_entry("event", S_IRUSR, acpi_root_dir); 123 if (entry) 124 entry->proc_fops = &acpi_system_event_ops; 125 else { 126 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 127 "Unable to create '%s' proc fs entry\n", 128 "event")); 129 error = -EFAULT; 130 } 131 return_VALUE(error); 132 } 133 134 subsys_initcall(acpi_event_init); 135