package/button-hotplug: handle KEY_RESTART and KEY_WPS_BUTTON codes as well
authorGabor Juhos <juhosg@openwrt.org>
Wed, 21 Apr 2010 19:07:14 +0000 (19:07 +0000)
committerGabor Juhos <juhosg@openwrt.org>
Wed, 21 Apr 2010 19:07:14 +0000 (19:07 +0000)
SVN-Revision: 21074

package/button-hotplug/src/button-hotplug.c

index 4bdf36435af9c735b0ccbd0b82266c95e1334525..0259a3fbcd874dd664924e66b8886a2d84d8e3f5 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 <net/sock.h>
 
 #define DRV_NAME       "button-hotplug"
-#define DRV_VERSION    "0.3.1"
+#define DRV_VERSION    "0.4.0"
 #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
 #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;
 
@@ -64,12 +59,35 @@ struct bh_event {
        struct work_struct      work;
 };
 
+struct bh_map {
+       unsigned int    code;
+       const char      *name;
+};
+
 extern struct sock *uevent_sock;
 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 */
 };
 
 /* -------------------------------------------------------------------------*/
@@ -169,7 +187,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;
@@ -194,23 +212,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;
 }
@@ -228,17 +256,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;