diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index 11e77a9..3a8ee50 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c @@ -43,6 +43,85 @@ struct gpio_keys_polled_dev { struct gpio_keys_button_data data[0]; }; +/** + * get_n_events_by_type() - returns maximum number of events per @type + * @type: type of button (%EV_KEY, %EV_SW) + * + * Return value of this function can be used to allocate bitmap + * large enough to hold all bits for given type. + */ +static inline int get_n_events_by_type(int type) +{ + BUG_ON(type != EV_SW && type != EV_KEY); + + return (type == EV_KEY) ? KEY_CNT : SW_CNT; +} + +/** + * gpio_keys_polled_attr_show_helper() - fill in stringified bitmap of buttons + * @ddata: pointer to drvdata + * @buf: buffer where stringified bitmap is written + * @type: button type (%EV_KEY, %EV_SW) + * + * Returns 0 on success or negative errno on failure. + */ +static ssize_t gpio_keys_polled_attr_show_helper( + struct gpio_keys_polled_dev *ddata, + char *buf, unsigned int type) +{ + int n_events = get_n_events_by_type(type); + unsigned long *bits; + ssize_t ret; + int i; + + bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL); + if (!bits) + return -ENOMEM; + + for (i = 0; i < ddata->pdata->nbuttons; i++) { + struct gpio_keys_button *bdata = &ddata->pdata->buttons[i]; + + if (bdata->type != type) + continue; + + __set_bit(bdata->code, bits); + } + + ret = scnprintf(buf, PAGE_SIZE - 1, "%*pbl", n_events, bits); + buf[ret++] = '\n'; + buf[ret] = '\0'; + + kfree(bits); + + return ret; +} + +static ssize_t gpio_keys_polled_show_keys(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct platform_device *pdev = to_platform_device(dev); + struct gpio_keys_polled_dev *ddata = platform_get_drvdata(pdev); + + return gpio_keys_polled_attr_show_helper(ddata, buf, EV_KEY); +} + +/* + * ATTRIBUTES: + * + * /sys/devices/platform/gpio-keys-polled/keys [ro] + */ +static DEVICE_ATTR(keys, S_IRUGO, gpio_keys_polled_show_keys, NULL); + +static struct attribute *gpio_keys_polled_attrs[] = { + &dev_attr_keys.attr, + NULL, +}; + +static struct attribute_group gpio_keys_polled_attr_group = { + .attrs = gpio_keys_polled_attrs, +}; + static void gpio_keys_polled_check_state(struct input_dev *input, struct gpio_keys_button *button, struct gpio_keys_button_data *bdata) @@ -286,6 +365,13 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) bdev->pdata = pdata; platform_set_drvdata(pdev, bdev); + error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_polled_attr_group); + if (error) { + dev_err(dev, "Unable to export keys, error: %d\n", + error); + return error; + } + error = input_register_polled_device(poll_dev); if (error) { dev_err(dev, "unable to register polled device, err=%d\n",