X-Git-Url: https://git.rohieb.name/openwrt.git/blobdiff_plain/0c8c774424e6e8a95187cdd254189a7e7ab05738..664467e66fa2c97a334ff7d4cd4392370a6d3abe:/package/button-hotplug/src/button-hotplug.c

diff --git a/package/button-hotplug/src/button-hotplug.c b/package/button-hotplug/src/button-hotplug.c
index f76b9277f..4a8c4a88e 100644
--- a/package/button-hotplug/src/button-hotplug.c
+++ b/package/button-hotplug/src/button-hotplug.c
@@ -1,7 +1,7 @@
 /*
  *  Button Hotplug driver
  *
- *  Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
  *
  *  Based on the diag.c - GPIO interface driver for Broadcom boards
  *    Copyright (C) 2006 Mike Baker <mbm@openwrt.org>,
@@ -21,19 +21,14 @@
 #include <linux/workqueue.h>
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
-#include <net/sock.h>
+#include <linux/kobject.h>
 
 #define DRV_NAME	"button-hotplug"
-#define DRV_VERSION	"0.3.1"
+#define DRV_VERSION	"0.4.1"
 #define DRV_DESC	"Button Hotplug driver"
 
 #define BH_SKB_SIZE	2048
 
-#define BH_BTN_MIN	BTN_0
-#define BH_BTN_MAX	BTN_9
-
-#define BH_BTN_COUNT	(BH_BTN_MAX - BH_BTN_MIN + 1)
-
 #define PFX	DRV_NAME ": "
 
 #undef BH_DEBUG
@@ -46,13 +41,17 @@
 
 #define BH_ERR(fmt, args...) printk(KERN_ERR "%s: " fmt, DRV_NAME, ##args )
 
+#ifndef BIT_MASK
+#define BIT_MASK(nr)            (1UL << ((nr) % BITS_PER_LONG))
+#endif
+
 struct bh_priv {
-	unsigned long		seen[BH_BTN_COUNT];
+	unsigned long		*seen;
 	struct input_handle	handle;
 };
 
 struct bh_event {
-	char			*name;
+	const char		*name;
 	char			*action;
 	unsigned long		seen;
 
@@ -60,12 +59,34 @@ struct bh_event {
 	struct work_struct	work;
 };
 
-extern struct sock *uevent_sock;
+struct bh_map {
+	unsigned int	code;
+	const char	*name;
+};
+
 extern u64 uevent_next_seqnum(void);
 
-static char *button_names[BH_BTN_COUNT] = {
-	"BTN_0", "BTN_1", "BTN_2", "BTN_3", "BTN_4",
-	"BTN_5", "BTN_6", "BTN_7", "BTN_8", "BTN_9"
+#define BH_MAP(_code, _name)		\
+	{				\
+		.code = (_code),	\
+		.name = (_name),	\
+	}
+
+static struct bh_map button_map[] = {
+	BH_MAP(BTN_0,		"BTN_0"),
+	BH_MAP(BTN_1,		"BTN_1"),
+	BH_MAP(BTN_2,		"BTN_2"),
+	BH_MAP(BTN_3,		"BTN_3"),
+	BH_MAP(BTN_4,		"BTN_4"),
+	BH_MAP(BTN_5,		"BTN_5"),
+	BH_MAP(BTN_6,		"BTN_6"),
+	BH_MAP(BTN_7,		"BTN_7"),
+	BH_MAP(BTN_8,		"BTN_8"),
+	BH_MAP(BTN_9,		"BTN_9"),
+	BH_MAP(KEY_RESTART,	"reset"),
+#ifdef KEY_WPS_BUTTON
+	BH_MAP(KEY_WPS_BUTTON,	"wps"),
+#endif /* KEY_WPS_BUTTON */
 };
 
 /* -------------------------------------------------------------------------*/
@@ -138,9 +159,6 @@ static void button_hotplug_work(struct work_struct *work)
 	struct bh_event *event = container_of(work, struct bh_event, work);
 	int ret = 0;
 
-	if (!uevent_sock)
-		goto out_free_event;
-
 	event->skb = alloc_skb(BH_SKB_SIZE, GFP_KERNEL);
 	if (!event->skb)
 		goto out_free_event;
@@ -154,7 +172,7 @@ static void button_hotplug_work(struct work_struct *work)
 		goto out_free_skb;
 
 	NETLINK_CB(event->skb).dst_group = 1;
-	netlink_broadcast(uevent_sock, event->skb, 0, 1, GFP_KERNEL);
+	broadcast_uevent(event->skb, 0, 1, GFP_KERNEL);
 
  out_free_skb:
 	if (ret) {
@@ -165,7 +183,7 @@ static void button_hotplug_work(struct work_struct *work)
 	kfree(event);
 }
 
-static int button_hotplug_create_event(char *name, unsigned long seen,
+static int button_hotplug_create_event(const char *name, unsigned long seen,
 		int pressed)
 {
 	struct bh_event *event;
@@ -190,23 +208,33 @@ static int button_hotplug_create_event(char *name, unsigned long seen,
 /* -------------------------------------------------------------------------*/
 
 #ifdef	CONFIG_HOTPLUG
+static int button_get_index(unsigned int code)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(button_map); i++)
+		if (button_map[i].code == code)
+			return i;
+
+	return -1;
+}
 static void button_hotplug_event(struct input_handle *handle,
 			   unsigned int type, unsigned int code, int value)
 {
 	struct bh_priv *priv = handle->private;
 	unsigned long seen = jiffies;
-	unsigned int btn;
+	int btn;
 
 	BH_DBG("event type=%u, code=%u, value=%d\n", type, code, value);
 
 	if (type != EV_KEY)
 		return;
 
-	if (code < BH_BTN_MIN || code > BH_BTN_MAX)
+	btn = button_get_index(code);
+	if (btn < 0)
 		return;
 
-	btn = code - BH_BTN_MIN;
-	button_hotplug_create_event(button_names[btn],
+	button_hotplug_create_event(button_map[btn].name,
 			(seen - priv->seen[btn]) / HZ, value);
 	priv->seen[btn] = seen;
 }
@@ -224,17 +252,20 @@ static int button_hotplug_connect(struct input_handler *handler,
 	int ret;
 	int i;
 
-	for (i = BH_BTN_MIN; i <= BH_BTN_MAX; i++)
-		if (test_bit(i, dev->keybit))
+	for (i = 0; i < ARRAY_SIZE(button_map); i++)
+		if (test_bit(button_map[i].code, dev->keybit))
 			break;
 
-	if (i > BH_BTN_MAX)
+	if (i == ARRAY_SIZE(button_map))
 		return -ENODEV;
 
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	priv = kzalloc(sizeof(*priv) +
+		       (sizeof(unsigned long) * ARRAY_SIZE(button_map)),
+		       GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
+	priv->seen = (unsigned long *) &priv[1];
 	priv->handle.private = priv;
 	priv->handle.dev = dev;
 	priv->handle.handler = handler;