美文网首页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