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(result); 63 64 chars_remaining = sprintf(str, "%s %s %08x %08x\n", 65 event.device_class ? event. 66 device_class : "<unknown>", 67 event.bus_id ? event. 68 bus_id : "<unknown>", event.type, 69 event.data); 70 ptr = str; 71 } 72 73 if (chars_remaining < count) { 74 count = chars_remaining; 75 } 76 77 if (copy_to_user(buffer, ptr, count)) 78 return_VALUE(-EFAULT); 79 80 *ppos += count; 81 chars_remaining -= count; 82 ptr += count; 83 84 return_VALUE(count); 85 } 86 87 static int acpi_system_close_event(struct inode *inode, struct file *file) 88 { 89 spin_lock_irq(&acpi_system_event_lock); 90 event_is_open = 0; 91 spin_unlock_irq(&acpi_system_event_lock); 92 return 0; 93 } 94 95 static unsigned int acpi_system_poll_event(struct file *file, poll_table * wait) 96 { 97 poll_wait(file, &acpi_bus_event_queue, wait); 98 if (!list_empty(&acpi_bus_event_list)) 99 return POLLIN | POLLRDNORM; 100 return 0; 101 } 102 103 static struct file_operations acpi_system_event_ops = { 104 .open = acpi_system_open_event, 105 .read = acpi_system_read_event, 106 .release = acpi_system_close_event, 107 .poll = acpi_system_poll_event, 108 }; 109 110 static int __init acpi_event_init(void) 111 { 112 struct proc_dir_entry *entry; 113 int error = 0; 114 115 ACPI_FUNCTION_TRACE("acpi_event_init"); 116 117 if (acpi_disabled) 118 return_VALUE(0); 119 120 /* 'event' [R] */ 121 entry = create_proc_entry("event", S_IRUSR, acpi_root_dir); 122 if (entry) 123 entry->proc_fops = &acpi_system_event_ops; 124 else { 125 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 126 "Unable to create '%s' proc fs entry\n", 127 "event")); 128 error = -EFAULT; 129 } 130 return_VALUE(error); 131 } 132 133 subsys_initcall(acpi_event_init); 134