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