OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [acpi/] [event.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
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
#include <net/netlink.h>
15
#include <net/genetlink.h>
16
 
17
#define _COMPONENT              ACPI_SYSTEM_COMPONENT
18
ACPI_MODULE_NAME("event");
19
 
20
#ifdef CONFIG_ACPI_PROC_EVENT
21
/* Global vars for handling event proc entry */
22
static DEFINE_SPINLOCK(acpi_system_event_lock);
23
int event_is_open = 0;
24
extern struct list_head acpi_bus_event_list;
25
extern wait_queue_head_t acpi_bus_event_queue;
26
 
27
static int acpi_system_open_event(struct inode *inode, struct file *file)
28
{
29
        spin_lock_irq(&acpi_system_event_lock);
30
 
31
        if (event_is_open)
32
                goto out_busy;
33
 
34
        event_is_open = 1;
35
 
36
        spin_unlock_irq(&acpi_system_event_lock);
37
        return 0;
38
 
39
      out_busy:
40
        spin_unlock_irq(&acpi_system_event_lock);
41
        return -EBUSY;
42
}
43
 
44
static ssize_t
45
acpi_system_read_event(struct file *file, char __user * buffer, size_t count,
46
                       loff_t * ppos)
47
{
48
        int result = 0;
49
        struct acpi_bus_event event;
50
        static char str[ACPI_MAX_STRING];
51
        static int chars_remaining = 0;
52
        static char *ptr;
53
 
54
        if (!chars_remaining) {
55
                memset(&event, 0, sizeof(struct acpi_bus_event));
56
 
57
                if ((file->f_flags & O_NONBLOCK)
58
                    && (list_empty(&acpi_bus_event_list)))
59
                        return -EAGAIN;
60
 
61
                result = acpi_bus_receive_event(&event);
62
                if (result)
63
                        return result;
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 -EFAULT;
80
 
81
        *ppos += count;
82
        chars_remaining -= count;
83
        ptr += count;
84
 
85
        return 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 const 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
#endif  /* CONFIG_ACPI_PROC_EVENT */
111
 
112
#ifdef CONFIG_NET
113
static unsigned int acpi_event_seqnum;
114
struct acpi_genl_event {
115
        acpi_device_class device_class;
116
        char bus_id[15];
117
        u32 type;
118
        u32 data;
119
};
120
 
121
/* attributes of acpi_genl_family */
122
enum {
123
        ACPI_GENL_ATTR_UNSPEC,
124
        ACPI_GENL_ATTR_EVENT,   /* ACPI event info needed by user space */
125
        __ACPI_GENL_ATTR_MAX,
126
};
127
#define ACPI_GENL_ATTR_MAX (__ACPI_GENL_ATTR_MAX - 1)
128
 
129
/* commands supported by the acpi_genl_family */
130
enum {
131
        ACPI_GENL_CMD_UNSPEC,
132
        ACPI_GENL_CMD_EVENT,    /* kernel->user notifications for ACPI events */
133
        __ACPI_GENL_CMD_MAX,
134
};
135
#define ACPI_GENL_CMD_MAX (__ACPI_GENL_CMD_MAX - 1)
136
 
137
#define ACPI_GENL_FAMILY_NAME           "acpi_event"
138
#define ACPI_GENL_VERSION               0x01
139
#define ACPI_GENL_MCAST_GROUP_NAME      "acpi_mc_group"
140
 
141
static struct genl_family acpi_event_genl_family = {
142
        .id = GENL_ID_GENERATE,
143
        .name = ACPI_GENL_FAMILY_NAME,
144
        .version = ACPI_GENL_VERSION,
145
        .maxattr = ACPI_GENL_ATTR_MAX,
146
};
147
 
148
static struct genl_multicast_group acpi_event_mcgrp = {
149
        .name = ACPI_GENL_MCAST_GROUP_NAME,
150
};
151
 
152
int acpi_bus_generate_netlink_event(const char *device_class,
153
                                      const char *bus_id,
154
                                      u8 type, int data)
155
{
156
        struct sk_buff *skb;
157
        struct nlattr *attr;
158
        struct acpi_genl_event *event;
159
        void *msg_header;
160
        int size;
161
        int result;
162
 
163
        /* allocate memory */
164
        size = nla_total_size(sizeof(struct acpi_genl_event)) +
165
            nla_total_size(0);
166
 
167
        skb = genlmsg_new(size, GFP_ATOMIC);
168
        if (!skb)
169
                return -ENOMEM;
170
 
171
        /* add the genetlink message header */
172
        msg_header = genlmsg_put(skb, 0, acpi_event_seqnum++,
173
                                 &acpi_event_genl_family, 0,
174
                                 ACPI_GENL_CMD_EVENT);
175
        if (!msg_header) {
176
                nlmsg_free(skb);
177
                return -ENOMEM;
178
        }
179
 
180
        /* fill the data */
181
        attr =
182
            nla_reserve(skb, ACPI_GENL_ATTR_EVENT,
183
                        sizeof(struct acpi_genl_event));
184
        if (!attr) {
185
                nlmsg_free(skb);
186
                return -EINVAL;
187
        }
188
 
189
        event = nla_data(attr);
190
        if (!event) {
191
                nlmsg_free(skb);
192
                return -EINVAL;
193
        }
194
 
195
        memset(event, 0, sizeof(struct acpi_genl_event));
196
 
197
        strcpy(event->device_class, device_class);
198
        strcpy(event->bus_id, bus_id);
199
        event->type = type;
200
        event->data = data;
201
 
202
        /* send multicast genetlink message */
203
        result = genlmsg_end(skb, msg_header);
204
        if (result < 0) {
205
                nlmsg_free(skb);
206
                return result;
207
        }
208
 
209
        result =
210
            genlmsg_multicast(skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC);
211
        if (result)
212
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
213
                                  "Failed to send a Genetlink message!\n"));
214
        return 0;
215
}
216
 
217
EXPORT_SYMBOL(acpi_bus_generate_netlink_event);
218
 
219
static int acpi_event_genetlink_init(void)
220
{
221
        int result;
222
 
223
        result = genl_register_family(&acpi_event_genl_family);
224
        if (result)
225
                return result;
226
 
227
        result = genl_register_mc_group(&acpi_event_genl_family,
228
                                        &acpi_event_mcgrp);
229
        if (result)
230
                genl_unregister_family(&acpi_event_genl_family);
231
 
232
        return result;
233
}
234
 
235
#else
236
int acpi_bus_generate_netlink_event(const char *device_class,
237
                                      const char *bus_id,
238
                                      u8 type, int data)
239
{
240
        return 0;
241
}
242
 
243
EXPORT_SYMBOL(acpi_bus_generate_netlink_event);
244
 
245
static int acpi_event_genetlink_init(void)
246
{
247
        return -ENODEV;
248
}
249
#endif
250
 
251
static int __init acpi_event_init(void)
252
{
253
#ifdef CONFIG_ACPI_PROC_EVENT
254
        struct proc_dir_entry *entry;
255
#endif
256
        int error = 0;
257
 
258
        if (acpi_disabled)
259
                return 0;
260
 
261
        /* create genetlink for acpi event */
262
        error = acpi_event_genetlink_init();
263
        if (error)
264
                printk(KERN_WARNING PREFIX
265
                       "Failed to create genetlink family for ACPI event\n");
266
 
267
#ifdef CONFIG_ACPI_PROC_EVENT
268
        /* 'event' [R] */
269
        entry = create_proc_entry("event", S_IRUSR, acpi_root_dir);
270
        if (entry)
271
                entry->proc_fops = &acpi_system_event_ops;
272
        else
273
                return -ENODEV;
274
#endif
275
 
276
        return 0;
277
}
278
 
279
fs_initcall(acpi_event_init);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.