[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <1182224403.5411.84.camel@localhost.localdomain>
Date: Tue, 19 Jun 2007 11:40:03 +0800
From: Zhang Rui <rui.zhang@...el.com>
To: linux-acpi@...r.kernel.org, netdev@...r.kernel.org
Cc: lenb@...nel.org, hadi@...erus.ca
Subject: [PATCH] ACPI: export acpi events via generic netlink
From: Zhang Rui <rui.zhang@...el.com>
Export ACPI events via Generic Netlink.
An "acpi_event" genetlink family message is sent
when an ACPI event is generated.
Note: The behavior of how ACPI event works nowadays is not changed.
Use genetlink to export ACPI event instead of
/proc/acpi/event someday, but not now.
This patch only adds the function of sending genetlink messages
when an ACPI event is generated.
Attachment is a simple user space utility which can be used to receive
acpi event notifications via netlink.
Thanks to Jamal for his great help.
Signed-off-by: Zhang Rui <rui.zhang@...el.com>
---
drivers/acpi/bus.c | 4 +
drivers/acpi/event.c | 166 +++++++++++++++++++++++++++++++++++++++++++++---
include/acpi/acpi_bus.h | 3
3 files changed, 165 insertions(+), 8 deletions(-)
Index: linux-2.6.22-rc5/drivers/acpi/bus.c
===================================================================
--- linux-2.6.22-rc5.orig/drivers/acpi/bus.c 2007-06-18 13:44:18.000000000 +0800
+++ linux-2.6.22-rc5/drivers/acpi/bus.c 2007-06-19 10:02:33.000000000 +0800
@@ -292,6 +292,10 @@
if (!device)
return -EINVAL;
+ if (acpi_bus_generate_genetlink_event(device, type, data))
+ printk(KERN_WARNING PREFIX
+ "Failed to generate an ACPI event via genetlink!\n");
+
/* drop event on the floor if no one's listening */
if (!event_is_open)
return 0;
Index: linux-2.6.22-rc5/drivers/acpi/event.c
===================================================================
--- linux-2.6.22-rc5.orig/drivers/acpi/event.c 2007-06-18 13:42:17.000000000 +0800
+++ linux-2.6.22-rc5/drivers/acpi/event.c 2007-06-19 11:07:15.000000000 +0800
@@ -11,6 +11,8 @@
#include <linux/init.h>
#include <linux/poll.h>
#include <acpi/acpi_drivers.h>
+#include <net/netlink.h>
+#include <net/genetlink.h>
#define _COMPONENT ACPI_SYSTEM_COMPONENT
ACPI_MODULE_NAME("event");
@@ -48,7 +50,6 @@
static int chars_remaining = 0;
static char *ptr;
-
if (!chars_remaining) {
memset(&event, 0, sizeof(struct acpi_bus_event));
@@ -106,23 +107,174 @@
.poll = acpi_system_poll_event,
};
+#ifdef CONFIG_NET
+unsigned int acpi_event_seqnum;
+struct acpi_genl_event {
+ acpi_device_class device_class;
+ char bus_id[15];
+ u32 type;
+ u32 data;
+};
+
+/* attributes of acpi_genl_family */
+enum {
+ ACPI_GENL_ATTR_UNSPEC,
+ ACPI_GENL_ATTR_EVENT, /* ACPI event info needed by user space */
+ __ACPI_GENL_ATTR_MAX,
+};
+#define ACPI_GENL_ATTR_MAX (__ACPI_GENL_ATTR_MAX - 1)
+
+/* commands supported by the acpi_genl_family */
+enum {
+ ACPI_GENL_CMD_UNSPEC,
+ ACPI_GENL_CMD_EVENT, /* kernel->user notifications for ACPI events */
+ __ACPI_GENL_CMD_MAX,
+};
+#define ACPI_GENL_CMD_MAX (__ACPI_GENL_CMD_MAX - 1)
+
+#define ACPI_GENL_NAME "acpi_event"
+#define ACPI_GENL_VERSION 0x01
+
+static struct genl_family acpi_event_genl_family = {
+ .id = GENL_ID_GENERATE,
+ .name = ACPI_GENL_NAME,
+ .version = ACPI_GENL_VERSION,
+ .maxattr = ACPI_GENL_ATTR_MAX,
+};
+
+/* .doit: standard command callback */
+static int acpi_genl_cmd_event(struct sk_buff *skb, struct genl_info *info)
+{
+ struct acpi_genl_event *event = info->userhdr;
+
+ if (!event)
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN, "ACPI event: NULL\n"));
+
+ return 0;
+}
+
+static struct genl_ops acpi_event_genl_ops = {
+ .cmd = ACPI_GENL_CMD_EVENT,
+ .doit = acpi_genl_cmd_event,
+};
+
+int acpi_bus_generate_genetlink_event(struct acpi_device *device,
+ u8 type, int data)
+{
+ struct sk_buff *skb;
+ struct nlattr *attr;
+ struct acpi_genl_event *event;
+ void *msg_header;
+ int size;
+ int result;
+
+ /* allocate memory */
+ size = nla_total_size(sizeof(struct acpi_genl_event)) +
+ nla_total_size(0);
+
+ skb = genlmsg_new(size, GFP_ATOMIC);
+ if (!skb)
+ return -ENOMEM;
+
+ /* add the genetlink message header */
+ msg_header = genlmsg_put(skb, 0, acpi_event_seqnum++,
+ &acpi_event_genl_family, 0,
+ ACPI_GENL_CMD_EVENT);
+ if (!msg_header) {
+ nlmsg_free(skb);
+ return -ENOMEM;
+ }
+
+ /* fill the data */
+ attr =
+ nla_reserve(skb, ACPI_GENL_ATTR_EVENT,
+ sizeof(struct acpi_genl_event));
+ if (!attr) {
+ nlmsg_free(skb);
+ return -EINVAL;
+ }
+
+ event = nla_data(attr);
+ if (!event) {
+ nlmsg_free(skb);
+ return -EINVAL;
+ }
+
+ memset(event, 0, sizeof(struct acpi_genl_event));
+
+ strcpy(event->device_class, device->pnp.device_class);
+ strcpy(event->bus_id, device->dev.bus_id);
+ event->type = type;
+ event->data = data;
+
+ /* send multicast genetlink message */
+ result = genlmsg_end(skb, msg_header);
+ if (result < 0) {
+ nlmsg_free(skb);
+ return result;
+ }
+
+ result =
+ genlmsg_multicast(skb, 0, acpi_event_genl_family.id, GFP_ATOMIC);
+ if (result)
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Failed to send a Genetlink message!\n"));
+ return 0;
+}
+EXPORT_SYMBOL(acpi_bus_generate_genetlink_event);
+
+static int acpi_event_genetlink_init(void)
+{
+ int result;
+
+ result = genl_register_family(&acpi_event_genl_family);
+ if (result)
+ return result;
+
+ result =
+ genl_register_ops(&acpi_event_genl_family, &acpi_event_genl_ops);
+ if (result)
+ genl_unregister_family(&acpi_event_genl_family);
+
+ return result;
+}
+
+#else
+int acpi_bus_generate_genetlink_event(struct acpi_device *device, u8 type,
+ int data)
+{
+ return 0;
+}
+EXPORT_SYMBOL(acpi_bus_generate_genetlink_event);
+
+static int acpi_event_genetlink_init(void)
+{
+ return -ENODEV;
+}
+#endif
+
static int __init acpi_event_init(void)
{
struct proc_dir_entry *entry;
int error = 0;
-
if (acpi_disabled)
return 0;
+ /* create genetlink for acpi event */
+ error = acpi_event_genetlink_init();
+ if (error)
+ printk(KERN_WARNING PREFIX
+ "Failed to create genetlink family for ACPI event\n");
+
/* 'event' [R] */
entry = create_proc_entry("event", S_IRUSR, acpi_root_dir);
if (entry)
entry->proc_fops = &acpi_system_event_ops;
- else {
- error = -ENODEV;
- }
- return error;
+ else
+ return -ENODEV;
+
+ return 0;
}
-subsys_initcall(acpi_event_init);
+fs_initcall(acpi_event_init);
Index: linux-2.6.22-rc5/include/acpi/acpi_bus.h
===================================================================
--- linux-2.6.22-rc5.orig/include/acpi/acpi_bus.h 2007-06-18 13:44:19.000000000 +0800
+++ linux-2.6.22-rc5/include/acpi/acpi_bus.h 2007-06-19 09:18:14.000000000 +0800
@@ -321,7 +321,8 @@
};
extern struct kset acpi_subsys;
-
+extern int acpi_bus_generate_genetlink_event(struct acpi_device *device,
+ u8 type, int data);
/*
* External Functions
*/
Download attachment "acpi_genl.tgz" of type "application/x-compressed-tar" (6472 bytes)
Powered by blists - more mailing lists