
一、设备树
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | adc-keys {
 compatible = "adc-keys";
 io-channels = <&saradc 2>;
 io-channel-names = "buttons";
 poll-interval = <100>;
 keyup-threshold-microvolt = <1800000>;
 adc-power-key {
 linux,code = <KEY_POWER>;
 label = "power key";
 press-threshold-microvolt = <0>;
 };
 };
 
 | 
二、上报键值
最关键的上报按键事件的代码:adc-keys.c:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 
 | static void adc_keys_poll(struct input_polled_dev *dev){
 struct adc_keys_state *st = dev->private;
 int i, value, ret;
 u32 diff, closest = 0xffffffff;
 int keycode = 0;
 
 ret = iio_read_channel_processed(st->channel, &value);
 if (unlikely(ret < 0)) {
 
 
 value = st->keyup_voltage;
 } else {
 for (i = 0; i < st->num_keys; i++) {
 
 diff = abs(st->map[i].voltage - value);
 if (diff < closest) {
 closest = diff;
 keycode = st->map[i].keycode;
 }
 }
 }
 
 if (abs(st->keyup_voltage - value) < closest)
 keycode = 0;
 
 
 if (st->last_key && st->last_key != keycode)
 input_report_key(dev->input, st->last_key, 0);
 
 if (keycode)
 input_report_key(dev->input, keycode, 1);
 
 input_sync(dev->input);
 st->last_key = keycode;
 }
 
 | 
三、使用实例
①修改设备树:
| 12
 3
 4
 5
 
 | adc_demo: adc_demo {status = "okay";
 compatible = "firefly,rk3399-adc";
 io-channels = <&saradc 0>;
 };
 
 | 
②编写驱动程序:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 
 | #include <linux/iio/types.h>#include <linux/input.h>
 #include <linux/input-polldev.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/property.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/iio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/pinctrl/consumer.h>
 
 static struct delayed_work	adc_poll_work;
 static struct iio_channel *chan;
 
 static void firefly_demo_adc_poll (struct work_struct *work)
 {
 int val,ret;
 int Vresult;
 
 
 
 
 
 
 
 
 
 
 ret = iio_read_channel_raw(chan, &val);
 Vresult = (1800 * val) / 1023;
 printk("the adc channel voltage is %d mV\n",Vresult);
 schedule_delayed_work(&adc_poll_work,msecs_to_jiffies(1000));
 }
 
 static int firefly_adc_probe(struct platform_device *pdev)
 {
 printk("firefly_adc_probe!\n");
 chan = iio_channel_get(&(pdev->dev), NULL);
 if (IS_ERR(chan)){
 chan = NULL;
 printk("%s() have not set adc chan\n", __FUNCTION__);
 return -1;
 }
 
 if (chan) {
 INIT_DELAYED_WORK(&adc_poll_work, firefly_demo_adc_poll);
 schedule_delayed_work(&adc_poll_work,msecs_to_jiffies(1000));
 }
 return 0;
 }
 
 static int firefly_adc_remove(struct platform_device *pdev)
 {
 printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
 iio_channel_release(chan);
 cancel_delayed_work_sync(&adc_poll_work);
 return 0;
 }
 
 static const struct of_device_id firefly_adc_match[] = {
 { .compatible = "firefly,rk3399-adc" },
 {},
 };
 
 static struct platform_driver firefly_adc_driver = {
 .probe      = firefly_adc_probe,
 .remove     = firefly_adc_remove,
 .driver     = {
 .name   = "firefly_adc",
 .owner  = THIS_MODULE,
 .of_match_table = firefly_adc_match,
 },
 };
 
 static int __init firefly_adc_init(void)
 {
 printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
 return platform_driver_register(&firefly_adc_driver);
 }
 
 static void __exit firefly_adc_exit(void)
 {
 printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
 platform_driver_unregister(&firefly_adc_driver);
 }
 
 module_init(firefly_adc_init);
 module_exit(firefly_adc_exit);
 
 MODULE_LICENSE("GPL");
 
 |