Allow user to poll the gpio keypad states in sysfs

Signed-off-by: Clark Li <[email protected]>
---
 drivers/input/keyboard/gpio_keys.c | 38 ++++++++++++++++++++++++++++++--------
 1 file changed, 30 insertions(+), 8 deletions(-)

diff --git a/drivers/input/keyboard/gpio_keys.c 
b/drivers/input/keyboard/gpio_keys.c
index b29ca65..d3a0536 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -3,6 +3,7 @@
  *
  * Copyright 2005 Phil Blundell
  * Copyright 2010, 2011 David Jander <[email protected]>
+ * Copyright 2014 Clark Li <[email protected]>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -49,6 +50,12 @@ struct gpio_keys_drvdata {
        struct gpio_button_data data[0];
 };
 
+/** What to display in sysfs attributes */
+enum gpio_attr_display {
+       gpio_attr_display_key,
+       gpio_attr_display_state
+};
+
 /*
  * SYSFS interface for enabling/disabling keys and switches:
  *
@@ -150,6 +157,7 @@ static void gpio_keys_enable_button(struct gpio_button_data 
*bdata)
  * @only_disabled: does caller want only those buttons that are
  *                 currently disabled or all buttons that can be
  *                 disabled
+ * @display: display the key or key state
  *
  * This function writes buttons that can be disabled to @buf. If
  * @only_disabled is true, then @buf contains only those buttons
@@ -158,12 +166,14 @@ static void gpio_keys_enable_button(struct 
gpio_button_data *bdata)
  */
 static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata,
                                          char *buf, unsigned int type,
-                                         bool only_disabled)
+                                         bool only_disabled,
+                                         enum gpio_attr_display display)
 {
        int n_events = get_n_events_by_type(type);
        unsigned long *bits;
        ssize_t ret;
        int i;
+       int state;
 
        bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL);
        if (!bits)
@@ -178,7 +188,15 @@ static ssize_t gpio_keys_attr_show_helper(struct 
gpio_keys_drvdata *ddata,
                if (only_disabled && !bdata->disabled)
                        continue;
 
-               __set_bit(bdata->button->code, bits);
+               if (display == gpio_attr_display_key)
+                       __set_bit(bdata->button->code, bits);
+               else if (display == gpio_attr_display_state) {
+                       state = gpio_get_value_cansleep(bdata->button->gpio)
+                               ? 1 : 0;
+                       state ^= bdata->button->active_low;
+                       if (state)
+                               __set_bit(bdata->button->code, bits);
+               }
        }
 
        ret = bitmap_scnlistprintf(buf, PAGE_SIZE - 2, bits, n_events);
@@ -251,7 +269,7 @@ out:
        return error;
 }
 
-#define ATTR_SHOW_FN(name, type, only_disabled)                                
\
+#define ATTR_SHOW_FN(name, type, only_disabled, display)               \
 static ssize_t gpio_keys_show_##name(struct device *dev,               \
                                     struct device_attribute *attr,     \
                                     char *buf)                         \
@@ -260,22 +278,25 @@ static ssize_t gpio_keys_show_##name(struct device *dev,  
        \
        struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);   \
                                                                        \
        return gpio_keys_attr_show_helper(ddata, buf,                   \
-                                         type, only_disabled);         \
+               type, only_disabled, display);                          \
 }
 
-ATTR_SHOW_FN(keys, EV_KEY, false);
-ATTR_SHOW_FN(switches, EV_SW, false);
-ATTR_SHOW_FN(disabled_keys, EV_KEY, true);
-ATTR_SHOW_FN(disabled_switches, EV_SW, true);
+ATTR_SHOW_FN(keys, EV_KEY, false, gpio_attr_display_key);
+ATTR_SHOW_FN(switches, EV_SW, false, gpio_attr_display_key);
+ATTR_SHOW_FN(states, EV_KEY, false, gpio_attr_display_state);
+ATTR_SHOW_FN(disabled_keys, EV_KEY, true, gpio_attr_display_key);
+ATTR_SHOW_FN(disabled_switches, EV_SW, true, gpio_attr_display_key);
 
 /*
  * ATTRIBUTES:
  *
  * /sys/devices/platform/gpio-keys/keys [ro]
  * /sys/devices/platform/gpio-keys/switches [ro]
+ * /sys/devices/platform/gpio-keys/states [ro]
  */
 static DEVICE_ATTR(keys, S_IRUGO, gpio_keys_show_keys, NULL);
 static DEVICE_ATTR(switches, S_IRUGO, gpio_keys_show_switches, NULL);
+static DEVICE_ATTR(states, S_IRUGO, gpio_keys_show_states, NULL);
 
 #define ATTR_STORE_FN(name, type)                                      \
 static ssize_t gpio_keys_store_##name(struct device *dev,              \
@@ -313,6 +334,7 @@ static DEVICE_ATTR(disabled_switches, S_IWUSR | S_IRUGO,
 static struct attribute *gpio_keys_attrs[] = {
        &dev_attr_keys.attr,
        &dev_attr_switches.attr,
+       &dev_attr_states.attr,
        &dev_attr_disabled_keys.attr,
        &dev_attr_disabled_switches.attr,
        NULL,
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to