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