linux/drivers/input/keyboard/adc-keys.c
<<
>>
Prefs
   1/*
   2 * Input driver for resistor ladder connected on ADC
   3 *
   4 * Copyright (c) 2016 Alexandre Belloni
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms of the GNU General Public License version 2 as published by
   8 * the Free Software Foundation.
   9 */
  10
  11#include <linux/err.h>
  12#include <linux/iio/consumer.h>
  13#include <linux/iio/types.h>
  14#include <linux/input.h>
  15#include <linux/input-polldev.h>
  16#include <linux/kernel.h>
  17#include <linux/module.h>
  18#include <linux/of.h>
  19#include <linux/platform_device.h>
  20#include <linux/property.h>
  21#include <linux/slab.h>
  22
  23struct adc_keys_button {
  24        u32 voltage;
  25        u32 keycode;
  26};
  27
  28struct adc_keys_state {
  29        struct iio_channel *channel;
  30        u32 num_keys;
  31        u32 last_key;
  32        u32 keyup_voltage;
  33        const struct adc_keys_button *map;
  34};
  35
  36static void adc_keys_poll(struct input_polled_dev *dev)
  37{
  38        struct adc_keys_state *st = dev->private;
  39        int i, value, ret;
  40        u32 diff, closest = 0xffffffff;
  41        int keycode = 0;
  42
  43        ret = iio_read_channel_processed(st->channel, &value);
  44        if (unlikely(ret < 0)) {
  45                /* Forcibly release key if any was pressed */
  46                value = st->keyup_voltage;
  47        } else {
  48                for (i = 0; i < st->num_keys; i++) {
  49                        diff = abs(st->map[i].voltage - value);
  50                        if (diff < closest) {
  51                                closest = diff;
  52                                keycode = st->map[i].keycode;
  53                        }
  54                }
  55        }
  56
  57        if (abs(st->keyup_voltage - value) < closest)
  58                keycode = 0;
  59
  60        if (st->last_key && st->last_key != keycode)
  61                input_report_key(dev->input, st->last_key, 0);
  62
  63        if (keycode)
  64                input_report_key(dev->input, keycode, 1);
  65
  66        input_sync(dev->input);
  67        st->last_key = keycode;
  68}
  69
  70static int adc_keys_load_keymap(struct device *dev, struct adc_keys_state *st)
  71{
  72        struct adc_keys_button *map;
  73        struct fwnode_handle *child;
  74        int i;
  75
  76        st->num_keys = device_get_child_node_count(dev);
  77        if (st->num_keys == 0) {
  78                dev_err(dev, "keymap is missing\n");
  79                return -EINVAL;
  80        }
  81
  82        map = devm_kmalloc_array(dev, st->num_keys, sizeof(*map), GFP_KERNEL);
  83        if (!map)
  84                return -ENOMEM;
  85
  86        i = 0;
  87        device_for_each_child_node(dev, child) {
  88                if (fwnode_property_read_u32(child, "press-threshold-microvolt",
  89                                             &map[i].voltage)) {
  90                        dev_err(dev, "Key with invalid or missing voltage\n");
  91                        fwnode_handle_put(child);
  92                        return -EINVAL;
  93                }
  94                map[i].voltage /= 1000;
  95
  96                if (fwnode_property_read_u32(child, "linux,code",
  97                                             &map[i].keycode)) {
  98                        dev_err(dev, "Key with invalid or missing linux,code\n");
  99                        fwnode_handle_put(child);
 100                        return -EINVAL;
 101                }
 102
 103                i++;
 104        }
 105
 106        st->map = map;
 107        return 0;
 108}
 109
 110static int adc_keys_probe(struct platform_device *pdev)
 111{
 112        struct device *dev = &pdev->dev;
 113        struct adc_keys_state *st;
 114        struct input_polled_dev *poll_dev;
 115        struct input_dev *input;
 116        enum iio_chan_type type;
 117        int i, value;
 118        int error;
 119
 120        st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
 121        if (!st)
 122                return -ENOMEM;
 123
 124        st->channel = devm_iio_channel_get(dev, "buttons");
 125        if (IS_ERR(st->channel))
 126                return PTR_ERR(st->channel);
 127
 128        if (!st->channel->indio_dev)
 129                return -ENXIO;
 130
 131        error = iio_get_channel_type(st->channel, &type);
 132        if (error < 0)
 133                return error;
 134
 135        if (type != IIO_VOLTAGE) {
 136                dev_err(dev, "Incompatible channel type %d\n", type);
 137                return -EINVAL;
 138        }
 139
 140        if (device_property_read_u32(dev, "keyup-threshold-microvolt",
 141                                     &st->keyup_voltage)) {
 142                dev_err(dev, "Invalid or missing keyup voltage\n");
 143                return -EINVAL;
 144        }
 145        st->keyup_voltage /= 1000;
 146
 147        error = adc_keys_load_keymap(dev, st);
 148        if (error)
 149                return error;
 150
 151        poll_dev = devm_input_allocate_polled_device(dev);
 152        if (!poll_dev) {
 153                dev_err(dev, "failed to allocate input device\n");
 154                return -ENOMEM;
 155        }
 156
 157        if (!device_property_read_u32(dev, "poll-interval", &value))
 158                poll_dev->poll_interval = value;
 159
 160        poll_dev->poll = adc_keys_poll;
 161        poll_dev->private = st;
 162
 163        input = poll_dev->input;
 164
 165        input->name = pdev->name;
 166        input->phys = "adc-keys/input0";
 167
 168        input->id.bustype = BUS_HOST;
 169        input->id.vendor = 0x0001;
 170        input->id.product = 0x0001;
 171        input->id.version = 0x0100;
 172
 173        __set_bit(EV_KEY, input->evbit);
 174        for (i = 0; i < st->num_keys; i++)
 175                __set_bit(st->map[i].keycode, input->keybit);
 176
 177        if (device_property_read_bool(dev, "autorepeat"))
 178                __set_bit(EV_REP, input->evbit);
 179
 180        error = input_register_polled_device(poll_dev);
 181        if (error) {
 182                dev_err(dev, "Unable to register input device: %d\n", error);
 183                return error;
 184        }
 185
 186        return 0;
 187}
 188
 189#ifdef CONFIG_OF
 190static const struct of_device_id adc_keys_of_match[] = {
 191        { .compatible = "adc-keys", },
 192        { }
 193};
 194MODULE_DEVICE_TABLE(of, adc_keys_of_match);
 195#endif
 196
 197static struct platform_driver __refdata adc_keys_driver = {
 198        .driver = {
 199                .name = "adc_keys",
 200                .of_match_table = of_match_ptr(adc_keys_of_match),
 201        },
 202        .probe = adc_keys_probe,
 203};
 204module_platform_driver(adc_keys_driver);
 205
 206MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@free-electrons.com>");
 207MODULE_DESCRIPTION("Input driver for resistor ladder connected on ADC");
 208MODULE_LICENSE("GPL v2");
 209