美文网首页Android开发Android开发经验谈Android开发
Android增加自定义Sensor -- ADC Sensor

Android增加自定义Sensor -- ADC Sensor

作者: 爱因私谈 | 来源:发表于2019-06-24 15:26 被阅读9次

    该文档将告诉你如何在Android系统上增加自定义Sensor,包含如何增加驱动、修改Hardware、Framework,以及APP如何使用该Sensor。

    源码

    完整源码请参考:Android-AdcSensor

    Driver

    1. 新建 kernel/drivers/input/sensors/adc/adcsensor.c
    /*
     * ADC Sensor driver
     *
     * Copyright  (C)  2016 - 2017 Topband. Ltd.
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 2 of the License, or
     * (at your option) any later version.
     *
     * This program is distributed in the hope that it will be a reference
     * to you, when you are integrating the ADC sensor into your system,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     * General Public License for more details.
     *
     * Author: shenhaibo
     * Version: 1.0.0
     * Release Date: 2019/6/17
     */
    
    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/device.h>
    #include <linux/errno.h>
    #include <linux/err.h>
    #include <linux/kernel.h>
    #include <linux/ctype.h>
    #include <linux/delay.h>
    #include <linux/idr.h>
    #include <linux/sched.h>
    #include <linux/slab.h>
    #include <linux/interrupt.h>
    #include <linux/signal.h>
    #include <linux/pm.h>
    #include <linux/notifier.h>
    #include <linux/fb.h>
    #include <linux/input.h>
    #include <linux/ioport.h>
    #include <linux/io.h>
    #include <linux/clk.h>
    #include <linux/pinctrl/consumer.h>
    #include <linux/platform_device.h>
    #include <linux/kthread.h>
    #include <linux/time.h>
    #include <linux/timer.h>
    #include <linux/regulator/consumer.h>
    #include <linux/gpio.h>
    #include <linux/of.h>
    #include <linux/of_irq.h>
    #include <linux/of_gpio.h>
    #include <linux/of_platform.h>
    #include <linux/miscdevice.h>
    #include <linux/uaccess.h>
    #include <linux/adc.h>
    #include <linux/slab.h>
    #include <linux/wakelock.h>
    
    #include <linux/iio/iio.h>
    #include <linux/iio/machine.h>
    #include <linux/iio/driver.h>
    #include <linux/iio/consumer.h>
    
    
    #define ADC_SENSOR_NAME "adcsensor"
    
    // ioctl cmd
    #define ADC_SENSOR_IOC_MAGIC  'a'
    
    #define ADC_SENSOR_IOC_ENABLE _IOW(ADC_SENSOR_IOC_MAGIC, 1, int)
    #define ADC_SENSOR_IOC_SET_RATE _IOW(ADC_SENSOR_IOC_MAGIC, 2, int)
    
    #define ADC_SENSOR_IOC_MAXNR 2
    
    #define EMPTY_ADVALUE           950
    #define DRIFT_ADVALUE           70
    #define INVALID_ADVALUE         -1
    
    #define POLL_INTERVAL_DEFAULT   1000
    
    #define HZ_TO_PERIOD_NSEC(hz)       (1000 * 1000 * 1000 / ((u32)(hz)))
    #define MS_TO_US(x)         ({ typeof(x) _x = (x); ((_x) * \
                                ((typeof(x)) 1000));})
    #define US_TO_NS(x)         (MS_TO_US(x))
    #define MS_TO_NS(x)         (US_TO_NS(MS_TO_US(x)))
    #define US_TO_MS(x)         ({ typeof(x) _x = (x); ((_x) / \
                                ((typeof(x)) 1000));})
    #define NS_TO_US(x)         (US_TO_MS(x))
    #define NS_TO_MS(x)         (US_TO_MS(NS_TO_US(x)))
    
    struct adc_sensor_data {
        struct platform_device *platform_dev;
        struct miscdevice adc_sensor_device;
        struct input_dev *input_dev;
        struct iio_channel *chan;
    
        bool enabled;
        unsigned int poll_interval;
        struct hrtimer hr_timer;
        struct work_struct input_work;
        ktime_t ktime;
    };
    
    struct adc_sensor_data *g_adc;
    
    static struct workqueue_struct *adc_sensor_workqueue = 0;
    
    static int adc_sensor_enable(struct adc_sensor_data *adc) {
        hrtimer_start(&adc->hr_timer, adc->ktime, HRTIMER_MODE_REL);
        adc->enabled = true;
        return 0;
    }
    
    static int adc_sensor_disable(struct adc_sensor_data *adc) {
        cancel_work_sync(&adc->input_work);
        hrtimer_cancel(&adc->hr_timer);
        adc->enabled = false;
        return 0;
    }
    
    static int adc_sensor_parse_dt(struct device *dev,
                                   struct adc_sensor_data *adc)
    {
        struct iio_channel *chan;
    
        chan = iio_channel_get(dev, NULL);
        if (IS_ERR(chan)) {
            dev_info(dev, "no io-channels defined\n");
            return -EINVAL;
        }
        adc->chan = chan;
    
        return 0;
    }
    
    static int adc_sensor_request_input_dev(struct adc_sensor_data *adc)
    {
        int ret = -1;
    
        adc->input_dev = input_allocate_device();
        if (adc->input_dev == NULL) {
            dev_err(&adc->platform_dev->dev, "Failed to to allocate input device\n");
            return -ENOMEM;
        }
    
        adc->input_dev->name = ADC_SENSOR_NAME;
        input_set_drvdata(adc->input_dev, adc);
    
        input_set_capability(adc->input_dev, EV_REL, REL_MISC);
    
        ret = input_register_device(adc->input_dev);
        if (ret) {
            dev_err(&adc->platform_dev->dev, "Register %s input device failed\n",
                    adc->input_dev->name);
            input_free_device(adc->input_dev);
            return -ENODEV;
        }
    
        return 0;
    }
    
    static int adc_sensor_dev_open(struct inode *inode, struct file *filp)
    {
        int ret = 0;
    
        struct adc_sensor_data *adc = container_of(filp->private_data,
                                      struct adc_sensor_data,
                                      adc_sensor_device);
        filp->private_data = adc;
        dev_info(&adc->platform_dev->dev,
                 "device node major=%d, minor=%d\n", imajor(inode), iminor(inode));
    
        return ret;
    }
    
    static long adc_sensor_dev_ioctl(struct file *pfile,
                                     unsigned int cmd, unsigned long arg)
    {
        int ret = 0;
        int data = 0;
        struct adc_sensor_data *adc = pfile->private_data;
    
        if (_IOC_TYPE(cmd) != ADC_SENSOR_IOC_MAGIC) {
            return -EINVAL;
        }
        if (_IOC_NR(cmd) > ADC_SENSOR_IOC_MAXNR) {
            return -EINVAL;
        }
    
        if (_IOC_DIR(cmd) & _IOC_READ) {
            ret = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
        } else if (_IOC_DIR(cmd) & _IOC_WRITE) {
            ret = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
        }
        if (ret) {
            return -EFAULT;
        }
    
        if (copy_from_user(&data, (int *)arg, sizeof(int))) {
            dev_err(&adc->platform_dev->dev,
                    "%s, copy from user failed\n", __func__);
            return -EFAULT;
        }
    
        dev_info(&adc->platform_dev->dev,
                 "%s, (%x, %lx): data=%d\n", __func__, cmd,
                 arg, data);
    
        switch (cmd) {
            case ADC_SENSOR_IOC_ENABLE:
                if (data > 0) {
                    adc_sensor_enable(adc);
                } else {
                    adc_sensor_disable(adc);
                }
                break;
    
            case ADC_SENSOR_IOC_SET_RATE:
                break;
    
            default:
                return -EINVAL;
        }
    
        return ret;
    }
    
    static const struct file_operations adc_sensor_dev_fops = {
        .owner = THIS_MODULE,
        .open = adc_sensor_dev_open,
        .unlocked_ioctl = adc_sensor_dev_ioctl
    };
    
    static int adc_sensor_adc_iio_read(struct adc_sensor_data *adc)
    {
        struct iio_channel *channel = adc->chan;
        int val, ret;
    
        if (!channel) {
            return INVALID_ADVALUE;
        }
    
        ret = iio_read_channel_raw(channel, &val);
        if (ret < 0) {
            dev_err(&adc->platform_dev->dev,
                    "%s, read channel error: %d\n", __func__, ret);
            return ret;
        }
    
        return val;
    }
    
    static void adc_sensor_report_event(struct adc_sensor_data *adc, s32 data)
    {
        struct input_dev *input = adc->input_dev;
    
        if (!adc->enabled) {
            return;
        }
    
        input_report_rel(input, REL_MISC, data);
        input_sync(input);
    }
    
    enum hrtimer_restart adc_sensor_poll_function_read(struct hrtimer *timer)
    {
        struct adc_sensor_data *adc;
    
        adc = container_of((struct hrtimer *)timer, struct adc_sensor_data, hr_timer);
    
        queue_work(adc_sensor_workqueue, &adc->input_work);
    
        return HRTIMER_NORESTART;
    }
    
    static void poll_function_work(struct work_struct *input_work)
    {
        int ret;
        struct adc_sensor_data *adc;
    
        adc = container_of((struct work_struct *)input_work,
                           struct adc_sensor_data, input_work);
    
        hrtimer_start(&adc->hr_timer, adc->ktime, HRTIMER_MODE_REL);
    
        ret = adc_sensor_adc_iio_read(adc);
        if (ret > INVALID_ADVALUE && ret < EMPTY_ADVALUE) {
            adc_sensor_report_event(adc, ret);
        }
    }
    
    static int adc_sensor_init(struct adc_sensor_data *adc)
    {
        hrtimer_init(&adc->hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        adc->hr_timer.function = &adc_sensor_poll_function_read;
    
        adc->poll_interval = POLL_INTERVAL_DEFAULT;
        adc->ktime = ktime_set(0, MS_TO_NS(adc->poll_interval));
        INIT_WORK(&adc->input_work, poll_function_work);
    
        return 0;
    }
    
    static int adc_sensor_probe(struct platform_device *pdev)
    {
        int ret = 0;
        struct adc_sensor_data *adc;
    
        adc = devm_kzalloc(&pdev->dev, sizeof(*adc), GFP_KERNEL);
        if (adc == NULL) {
            dev_err(&pdev->dev, "Failed to alloc ts memory");
            return -ENOMEM;
        }
    
        g_adc = adc;
    
        if (pdev->dev.of_node) {
            ret = adc_sensor_parse_dt(&pdev->dev, adc);
            if (ret) {
                dev_err(&pdev->dev, "Failed to parse dts\n");
                goto exit_free_data;
            }
        }
    
        adc->platform_dev = pdev;
    
        ret = adc_sensor_request_input_dev(adc);
        if (ret < 0) {
            dev_err(&pdev->dev, "Failed to register input device\n");
            goto exit_free_data;
        }
    
        platform_set_drvdata(pdev, adc);
    
        if(adc_sensor_workqueue == 0)
            adc_sensor_workqueue = create_workqueue("adc_sensor_workqueue");
    
        ret = adc_sensor_init(adc);
        if (ret < 0) {
            dev_err(&pdev->dev, "failed to init sensor\n");
            goto exit_unreg_input_dev;
        }
    
        adc->adc_sensor_device.minor = MISC_DYNAMIC_MINOR;
        adc->adc_sensor_device.name = ADC_SENSOR_NAME;
        adc->adc_sensor_device.fops = &adc_sensor_dev_fops;
    
        ret = misc_register(&adc->adc_sensor_device);
        if (ret) {
            dev_err(&pdev->dev, "Failed to misc_register\n");
            goto exit_unreg_input_dev;
        }
    
        dev_info(&pdev->dev, "%s, over\n", __func__);
        return 0;
    
    exit_unreg_input_dev:
        input_unregister_device(adc->input_dev);
    
    exit_free_data:
        devm_kfree(&pdev->dev, adc);
    
        return ret;
    }
    
    static int adc_sensor_remove(struct platform_device *pdev)
    {
        struct adc_sensor_data *adc = platform_get_drvdata(pdev);
        
        input_unregister_device(adc->input_dev);
        kfree(adc);
    
        return 0;
    }
    
    static const struct of_device_id adc_sensor_of_match[] = {
        { .compatible =  "adcsensor"},
        {},
    };
    
    MODULE_DEVICE_TABLE(of, adc_sensor_of_match);
    
    static struct platform_driver adc_sensor_driver = {
        .probe = adc_sensor_probe,
        .remove = adc_sensor_remove,
        .driver = {
            .name = ADC_SENSOR_NAME,
            .owner  = THIS_MODULE,
            .of_match_table = adc_sensor_of_match,
        },
    };
    
    module_platform_driver(adc_sensor_driver);
    
    MODULE_AUTHOR("shenhb@topband.com.cn");
    MODULE_DESCRIPTION("ADC Sensor for appcation to detect battery voltage");
    MODULE_VERSION("1.0");
    MODULE_LICENSE("GPL");
    
    

    注意:

    • ==注意input设备的设备名,因为Android Sensor HAL层是通过此设备名找到对应的input设备文件的。==
    • ==注意input事件上报类型,因为Android Sensor HAL层轮训input事件时要与之一致。==
    • ==ioctl至少实现enable与set rate两个功能,enable用于开关Sensor,set rate用于设置数据采样频率。==
    • ==数据读取采用timer轮训方式==
    2. 在驱动源文件同目录下增加Kconfig与Makefile

    kernel/drivers/input/sensors/adc/Kconfig

    config SENSORS_ADC
             tristate "ADC sensor"
             help
               This driver support the ADC sensor.
    
               To compile this driver as a module, choose M here. The module
           will be called adc.
    

    kernel/drivers/input/sensors/adc/Makefile

    obj-$(CONFIG_SENSORS_ADC) += adcsensor.o
    
    3. 修改上层Kconfig与Makefile

    kernel/drivers/input/sensors/Kconfig

     source "drivers/input/sensors/pressure/Kconfig"
     source "drivers/input/sensors/hall/Kconfig"
     source "drivers/input/sensors/lsm6ds3/Kconfig"
    +source "drivers/input/sensors/adc/Kconfig"
    

    kernel/drivers/input/sensors/Makefile

     obj-$(CONFIG_PRESSURE_DEVICE)      += pressure/
     obj-$(CONFIG_HALL_DEVICE)          += hall/
     obj-$(CONFIG_INPUT_LSM6DS3)        += lsm6ds3/
    +obj-$(CONFIG_SENSORS_ADC)          += adc/
    
    4. 在内核config中打开
     # CONFIG_MPU_SENSORS_BMA085 is not set
     # CONFIG_MPU_USERSPACE_DEBUG is not set
     CONFIG_INPUT_LSM6DS3=y
    +CONFIG_SENSORS_ADC=y
    
    5. 编译kernel

    编译kernel,烧录,启动,通过getevent能看到对应的input设备:

    130|shell@rk312x_bt:/ # getevent
    add device 1: /dev/input/event9
      name:     "PixArt USB Optical Mouse"
    add device 2: /dev/input/event6
      name:     "ST LSM6DS3 Tilt Sensor"
    add device 3: /dev/input/event5
      name:     "ST LSM6DS3 Step Detector Sensor"
    add device 4: /dev/input/event4
      name:     "ST LSM6DS3 Step Counter Sensor"
    add device 5: /dev/input/event3
      name:     "ST LSM6DS3 Significant Motion Sensor"
    add device 6: /dev/input/event2
      name:     "gyro"
    add device 7: /dev/input/event1
      name:     "gsensor"
    add device 8: /dev/input/event8
      name:     "adcsensor"
    add device 9: /dev/input/event0
      name:     "rk816_pwrkey"
    add device 10: /dev/input/event7
      name:     "rk29-keypad"
    

    Hardware

    1. 新建 hardware\rockchip\sensor\st\AdcSensor.cpp
    /*********************************************************************************
    * Copyright(C), 2019-2025, ayst.shen@foxmail.com
    * FileName: AdcSensor.cpp
    * Author: Shen Haibo
    * Version: 1.0.0
    * Date: 2019-6-18
    * Description:
    *     Custom ADC sensor, for get the voltage value.
    *
    * Revision:
    *     Date:
    *     Reviser:
    *     Description:
    *********************************************************************************/
    
    
    #include <fcntl.h>
    #include <errno.h>
    #include <math.h>
    #include <poll.h>
    #include <unistd.h>
    #include <dirent.h>
    #include <math.h>
    #include <sys/select.h>
    #include <cutils/log.h>
    #include <utils/BitSet.h>
    #include <cutils/properties.h>
    #include <linux/ioctl.h>
    
    #include "AdcSensor.h"
    
    #define ADC_IOC_MAGIC               'a'
    
    #define ADC_IOC_ENABLE              _IOW(ADC_IOC_MAGIC, 1, int)
    #define ADC_IOC_SET_RATE            _IOW(ADC_IOC_MAGIC, 2, int)
    
    AdcSensor::AdcSensor()
        : SensorBase(ADC_DEVICE_NAME, "adcsensor"),
          mEnabled(0),
          mInputReader(32)
    {
        mPendingEvent.version = sizeof(sensors_event_t);
        mPendingEvent.sensor = ID_ADC;
        mPendingEvent.type = SENSOR_TYPE_ADC;
        memset(mPendingEvent.data, 0x00, sizeof(mPendingEvent.data));
    
        int err = 0;
        err = open_device();
        err = err < 0 ? -errno : 0;
        if (err) {
            LOGE("%s:%s\n", __func__, strerror(-err));
            return;
        }
    }
    
    AdcSensor::~AdcSensor()
    {
        if (mEnabled) {
            enable(0, 0);
        }
    
        if (dev_fd > 0) {
            close(dev_fd);
            dev_fd = -1;
        }
    }
    
    int AdcSensor::enable(int32_t, int en)
    {
        int newState = en ? 1 : 0;
        int err = 0;
    
        if (newState != mEnabled) {
            if (dev_fd < 0) {
                open_device();
            }
    
            if (0 > (err = ioctl(dev_fd, ADC_IOC_ENABLE, &newState))) {
                LOGE("fail to perform ADC_IOC_ENABLE, err = %d, error is '%s'", err, strerror(errno));
                goto EXIT;
            }
    
            mEnabled = newState;
        }
    
    EXIT:
        return err;
    }
    
    int AdcSensor::setDelay(int32_t handle, int64_t ns)
    {
        int err = 0;
    
        if (ns < 0) {
            return -EINVAL;
        }
    
        if (dev_fd < 0) {
            open_device();
        }
    
        short delay = ns / 1000000;
    
        if ((err = ioctl(dev_fd, ADC_IOC_SET_RATE, &delay)) < 0) {
            LOGE("fail to perform ADC_IOC_SET_RATE, result = %d, error is '%s'", err, strerror(errno));
        }
    
        return err;
    }
    
    int AdcSensor::isActivated(int /* handle */)
    {
        return mEnabled;
    }
    
    int AdcSensor::readEvents(sensors_event_t* data, int count)
    {
        if (count < 1) {
            return -EINVAL;
        }
    
        ssize_t n = mInputReader.fill(data_fd);
        if (n < 0) {
            return n;
        }
    
        int numEventReceived = 0;
        input_event const* event;
    
        while (count && mInputReader.readEvent(&event)) {
            int type = event->type;
    
            LOGI("AdcSensor: read event (type=%d, code=%d)", type, event->code);
    
            if (type == EV_REL) {
                processEvent(event->code, event->value);
            } else if (type == EV_SYN) {
                mPendingEvent.timestamp = getTimestamp();
                *data++ = mPendingEvent;
                count--;
                numEventReceived++;
            } else {
                LOGE("AdcSensor: unknown event (type=%d, code=%d)", type, event->code);
            }
    
            mInputReader.next();
        }
    
        return numEventReceived;
    }
    
    void AdcSensor::processEvent(int code, int value)
    {
        switch (code) {
            case EVENT_TYPE_ADC:
                mPendingEvent.voltage = value;
                break;
        }
    }
    

    注意:

    • ==ADC_DEVICE_NAME 驱动中注册的设备文件,用于ioctl开关Sensor和设置轮训频率。==
    • ==“adcsensor” 为input设备名,用于事件读取。==
    • ==readEvents() 中用到的事件类型要与驱动中一致,否则无法读取事件。==
    • ==processEvent() 中主要对数据进一步加工。==
    2. 增加头文件

    hardware\rockchip\sensor\st\AdcSensor.h

    /*********************************************************************************
    * Copyright(C), 2019-2025, ayst.shen@foxmail.com
    * FileName: AdcSensor.h
    * Author: Shen Haibo
    * Version: 1.0.0
    * Date: 2019-6-18
    * Description:
    *     Custom ADC sensor, for get the voltage value.
    *
    * Revision:
    *     Date:
    *     Reviser:
    *     Description:
    *********************************************************************************/
    
    
    #ifndef ANDROID_ADC_SENSOR_H
    #define ANDROID_ADC_SENSOR_H
    
    #include <stdint.h>
    #include <errno.h>
    #include <sys/cdefs.h>
    #include <sys/types.h>
    
    #include "nusensors.h"
    #include "SensorBase.h"
    #include "InputEventReader.h"
    
    struct input_event;
    
    class AdcSensor : public SensorBase
    {
        private:
            int mEnabled;
            InputEventCircularReader mInputReader;
            sensors_event_t mPendingEvent;
    
        public:
            AdcSensor();
            virtual ~AdcSensor();
            virtual int readEvents(sensors_event_t* data, int count);
            void processEvent(int code, int value);
            virtual int setDelay(int32_t handle, int64_t ns);
            virtual int enable(int32_t handle, int enabled);
            virtual int isActivated(int handle);
    };
    
    #endif  // ANDROID_ADC_SENSOR_H
    
    
    3. 将源文件加入到Android.mk
    diff --git a/hardware/rockchip/sensor/st/Android.mk b/hardware/rockchip/sensor/st/Android.mk
    index 50b2364..f602c90 100755
    --- a/hardware/rockchip/sensor/st/Android.mk
    +++ b/hardware/rockchip/sensor/st/Android.mk
    @@ -41,6 +41,7 @@ LOCAL_SRC_FILES :=                        \
                    ProximitySensor.cpp     \
                    PressureSensor.cpp      \
                    TemperatureSensor.cpp       \
    +               AdcSensor.cpp
    
    4. 修改其它HAL文件,将新增的AdcSensor加入其中
    diff --git a/hardware/libhardware/include/hardware/sensors.h b/hardware/libhardware/include/hardware/sensors.h
    old mode 100644
    new mode 100755
    index f0773d5..6f38243
    --- a/hardware/libhardware/include/hardware/sensors.h
    +++ b/hardware/libhardware/include/hardware/sensors.h
    @@ -603,6 +603,15 @@ enum {
     #define SENSOR_STRING_TYPE_PICK_UP_GESTURE                     "android.sensor.pick_up_gesture"
     
     /**
    + * SENSOR_TYPE_ADC
    + * reporting-mode: one-shot
    + *
    + * Custom ADC sensor, for get the voltage value.
    + */
    +#define SENSOR_TYPE_ADC                                        (26)
    +#define SENSOR_STRING_TYPE_ADC                                 "android.sensor.adc"
    +
    +/**
      * Values returned by the accelerometer in various locations in the universe.
      * all values are in SI units (m/s^2)
      */
    @@ -728,6 +737,9 @@ typedef struct sensors_event_t {
                 /* temperature is in degrees centigrade (Celsius) */
                 float           temperature;
     
    +            /* voltage values are in voltage(mV)*/
    +            float           voltage;
    +
                 /* distance in centimeters */
                 float           distance;
                 
    diff --git a/hardware/rockchip/sensor/st/nusensors.cpp b/hardware/rockchip/sensor/st/nusensors.cpp
    index f6fbd36..c71f07c 100755
    --- a/hardware/rockchip/sensor/st/nusensors.cpp
    +++ b/hardware/rockchip/sensor/st/nusensors.cpp
    @@ -36,6 +36,7 @@
     #include "GyroSensor.h"
     #include "PressureSensor.h"
     #include "TemperatureSensor.h"
    +#include "AdcSensor.h"
     
     #if defined(CALIBRATION_SUPPORT)
     typedef        unsigned short      uint16;
    @@ -158,6 +159,7 @@ private:
             gyro            = 4, 
             pressure        = 5,
             temperature        = 6,
    +        adc             = 7,
             numSensorDrivers,
             numFds,
         };
    @@ -185,6 +187,8 @@ private:
                    return pressure;
                case ID_TMP:
                    return temperature;
    +            case ID_ADC:
    +               return adc;
             }
             return -EINVAL;
         }
    @@ -232,6 +236,11 @@ sensors_poll_context_t::sensors_poll_context_t()
         mPollFds[temperature].events = POLLIN;
         mPollFds[temperature].revents = 0;
     
    +    mSensors[adc] = new AdcSensor();
    +    mPollFds[adc].fd = mSensors[adc]->getFd();
    +    mPollFds[adc].events = POLLIN;
    +    mPollFds[adc].revents = 0;
    +
         int wakeFds[2];
         int result = pipe(wakeFds);
         LOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno));
    diff --git a/hardware/rockchip/sensor/st/nusensors.h b/hardware/rockchip/sensor/st/nusensors.h
    index 5aab787..e6d8edd 100755
    --- a/hardware/rockchip/sensor/st/nusensors.h
    +++ b/hardware/rockchip/sensor/st/nusensors.h
    @@ -61,6 +61,7 @@ int init_nusensors(hw_module_t const* module, hw_device_t** device);
     #define ID_GY   (5)
     #define ID_PR   (6)
     #define ID_TMP  (7)
    +#define ID_ADC  (8)
     
    @@ -81,6 +82,7 @@ int init_nusensors(hw_module_t const* module, hw_device_t** device);
     #define GY_DEVICE_NAME      LSM6DS3_GYRO_DEV_PATH
     #define PR_DEVICE_NAME      "/dev/pressure"
     #define TMP_DEVICE_NAME     "/dev/temperature"
    +#define ADC_DEVICE_NAME     "/dev/adcsensor"
     
     // for LSM6DS3
     #define GSENSOR_IOC_ENABLE          LSM6DS3_IOC_ENABLE
    @@ -115,7 +117,7 @@ int init_nusensors(hw_module_t const* module, hw_device_t** device);
     
     #define EVENT_TYPE_PRESSURE         ABS_PRESSURE
     
    +#define EVENT_TYPE_ADC              REL_MISC
    
    diff --git a/hardware/rockchip/sensor/st/sensors.c b/hardware/rockchip/sensor/st/sensors.c
    index ad06d0b..9ca012e 100755
    --- a/hardware/rockchip/sensor/st/sensors.c
    +++ b/hardware/rockchip/sensor/st/sensors.c
    @@ -32,7 +32,7 @@
     
     static const struct sensor_t sSensorList[] = {
        { .name       = "Gravity sensor",
               .vendor     = "The Android Open Source Project",
               .version    = 1,
               .handle     = SENSORS_HANDLE_BASE+ID_A,
    @@ -129,7 +129,18 @@ static const struct sensor_t sSensorList[] = {
               .minDelay   = 5000,
               .reserved   = {}
             },
    +
    +    { .name       = "Adc sensor",
    +          .vendor     = "The Android Open Source Project",
    +          .version    = 1,
    +          .handle     = SENSORS_HANDLE_BASE+ID_ADC,
    +          .type       = SENSOR_TYPE_ADC,
    +          .maxRange   = 110000.0f,
    +          .resolution = 1.0f,
    +          .power      = 1.0f,
    +          .minDelay   = 5000,
    +          .reserved   = {}
    +        },
     };
     
    

    Framework

    1. framework参考下面修改
    diff --git a/frameworks/base/core/java/android/hardware/LegacySensorManager.java b/frameworks/base/core/java/android/hardware/LegacySensorManager.java
    old mode 100644
    new mode 100755
    index f959093..806925e
    --- a/frameworks/base/core/java/android/hardware/LegacySensorManager.java
    +++ b/frameworks/base/core/java/android/hardware/LegacySensorManager.java
    @@ -81,6 +81,9 @@ final class LegacySensorManager {
                         result |= SensorManager.SENSOR_ORIENTATION
                                 | SensorManager.SENSOR_ORIENTATION_RAW;
                         break;
    +                case Sensor.TYPE_ADC:
    +                    result |= SensorManager.SENSOR_ADC;
    +                    break;
                 }
             }
             return result;
    @@ -101,6 +104,8 @@ final class LegacySensorManager {
                     Sensor.TYPE_ORIENTATION, listener, sensors, rate) || result;
             result = registerLegacyListener(SensorManager.SENSOR_TEMPERATURE,
                     Sensor.TYPE_TEMPERATURE, listener, sensors, rate) || result;
    +        result = registerLegacyListener(SensorManager.SENSOR_ADC,
    +                Sensor.TYPE_ADC, listener, sensors, rate) || result;
             return result;
         }
     
    @@ -155,6 +160,8 @@ final class LegacySensorManager {
                     listener, sensors);
             unregisterLegacyListener(SensorManager.SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE,
                     listener, sensors);
    +        unregisterLegacyListener(SensorManager.SENSOR_ADC, Sensor.TYPE_ADC,
    +                listener, sensors);
         }
     
         private void unregisterLegacyListener(int legacyType, int type,
    diff --git a/frameworks/base/core/java/android/hardware/Sensor.java b/frameworks/base/core/java/android/hardware/Sensor.java
    old mode 100644
    new mode 100755
    index cf6a779..18927e7
    --- a/frameworks/base/core/java/android/hardware/Sensor.java
    +++ b/frameworks/base/core/java/android/hardware/Sensor.java
    @@ -512,6 +512,23 @@ public final class Sensor {
         public static final String STRING_TYPE_PICK_UP_GESTURE = "android.sensor.pick_up_gesture";
     
         /**
    +     * A constant describing a pick up sensor.
    +     *
    +     * Custom ADC sensor, for get the voltage value.
    +     *
    +     * @hide Expected to be used internally for always on display.
    +     */
    +    public static final int TYPE_ADC = 26;
    +
    +    /**
    +     * A constant string describing a pick up sensor.
    +     *
    +     * @hide This sensor is expected to be used internally for always on display.
    +     * @see #TYPE_ADC
    +     */
    +    public static final String STRING_TYPE_ADC = "android.sensor.adc";
    +
    +    /**
          * A constant describing all sensor types.
          */
         public static final int TYPE_ALL = -1;
    diff --git a/frameworks/base/core/java/android/hardware/SensorManager.java b/frameworks/base/core/java/android/hardware/SensorManager.java
    old mode 100644
    new mode 100755
    index e4e5a8c..63d46dc
    --- a/frameworks/base/core/java/android/hardware/SensorManager.java
    +++ b/frameworks/base/core/java/android/hardware/SensorManager.java
    @@ -164,6 +164,15 @@ public abstract class SensorManager {
         public static final int SENSOR_ORIENTATION_RAW = 1 << 7;
     
         /**
    +     * A constant describing an adc sensor. See
    +     * {@link android.hardware.SensorListener SensorListener} for more details.
    +     *
    +     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    +     */
    +    @Deprecated
    +    public static final int SENSOR_ADC = 1 << 8;
    +
    +    /**
          * A constant that includes all sensors
          *
          * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    diff --git a/frameworks/native/include/android/sensor.h b/frameworks/native/include/android/sensor.h
    old mode 100644
    new mode 100755
    index d58c460..3ca6287
    --- a/frameworks/native/include/android/sensor.h
    +++ b/frameworks/native/include/android/sensor.h
    @@ -59,7 +59,8 @@ enum {
         ASENSOR_TYPE_MAGNETIC_FIELD     = 2,
         ASENSOR_TYPE_GYROSCOPE          = 4,
         ASENSOR_TYPE_LIGHT              = 5,
    -    ASENSOR_TYPE_PROXIMITY          = 8
    +    ASENSOR_TYPE_PROXIMITY          = 8,
    +    ASENSOR_TYPE_ADC                = 26
     };
     
     /*
    @@ -160,6 +161,7 @@ typedef struct ASensorEvent {
                 ASensorVector   acceleration;
                 ASensorVector   magnetic;
                 float           temperature;
    +            float           voltage;
                 float           distance;
                 float           light;
                 float           pressure;
    diff --git a/frameworks/native/include/gui/Sensor.h b/frameworks/native/include/gui/Sensor.h
    old mode 100644
    new mode 100755
    index 28a08e2..37b5958
    --- a/frameworks/native/include/gui/Sensor.h
    +++ b/frameworks/native/include/gui/Sensor.h
    @@ -49,7 +49,8 @@ public:
             TYPE_MAGNETIC_FIELD = ASENSOR_TYPE_MAGNETIC_FIELD,
             TYPE_GYROSCOPE      = ASENSOR_TYPE_GYROSCOPE,
             TYPE_LIGHT          = ASENSOR_TYPE_LIGHT,
    -        TYPE_PROXIMITY      = ASENSOR_TYPE_PROXIMITY
    +        TYPE_PROXIMITY      = ASENSOR_TYPE_PROXIMITY,
    +        TYPE_ADC            = ASENSOR_TYPE_ADC
         };
     
                 Sensor();
    diff --git a/hardware/libhardware/include/hardware/sensors.h b/hardware/libhardware/include/hardware/sensors.h
    old mode 100644
    new mode 100755
    index f0773d5..6f38243
    --- a/hardware/libhardware/include/hardware/sensors.h
    +++ b/hardware/libhardware/include/hardware/sensors.h
    @@ -603,6 +603,15 @@ enum {
     #define SENSOR_STRING_TYPE_PICK_UP_GESTURE                     "android.sensor.pick_up_gesture"
     
     /**
    + * SENSOR_TYPE_ADC
    + * reporting-mode: one-shot
    + *
    + * Custom ADC sensor, for get the voltage value.
    + */
    +#define SENSOR_TYPE_ADC                                        (26)
    +#define SENSOR_STRING_TYPE_ADC                                 "android.sensor.adc"
    +
    +/**
      * Values returned by the accelerometer in various locations in the universe.
      * all values are in SI units (m/s^2)
      */
    @@ -728,6 +737,9 @@ typedef struct sensors_event_t {
                 /* temperature is in degrees centigrade (Celsius) */
                 float           temperature;
     
    +            /* voltage values are in voltage(mV)*/
    +            float           voltage;
    +
                 /* distance in centimeters */
                 float           distance;
     
    
    2. 编译更新API
    make update-api
    

    APP使用

    demo下载

    Android增加自定义Sensor后,APP的使用方式同Android其它默认Sensor,只需要将Sensor type改为 Sensor.TYPE_ADC 即可。

    获取到的valtage值为ADC原始值,没有经过计算转换,需要APP根据电压与值的对应关系换算。

    下面为监听ADC Sensor电压变化为实现方法,仅供参考:

    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    if (null != mSensorManager) {
        Sensor adcSensor = mSensorManager.getDefaultSensor(26); // 26: Sensor.TYPE_ADC
            if (adcSensor != null) {
                mAdcSensorEventListener = new SensorEventListener() {
                    @Override
                    public void onSensorChanged(SensorEvent event) {
                        float voltage = event.values[0];
                        mVoltageTv.setText(voltage + "");
                    }
    
                    @Override
                    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    
                    }
                };
                mSensorManager.registerListener(mAdcSensorEventListener, adcSensor, SensorManager.SENSOR_DELAY_NORMAL);
            }
    }
    

    相关文章

      网友评论

        本文标题:Android增加自定义Sensor -- ADC Sensor

        本文链接:https://www.haomeiwen.com/subject/tukoqctx.html