hostapd: add a workaround for driver issues in various android devices with texas...
[openwrt.git] / package / button-hotplug / src / button-hotplug.c
index f76b927..4a8c4a8 100644 (file)
@@ -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>,
 #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
 
 #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;
This page took 0.023137 seconds and 4 git commands to generate.