【干货】Android系统定制基础篇:第十八部分-Android自定义Sensor-人体感应Sensor

如何在 Android 系统上增加人体接近感应 Sensor,包含如何增加驱动、修改 Hardware、Framework,以及 APP 如何使用该 Sensor。

驱动

新建 kernel/drivers/input/sensors/mwsensor/mwsensor.c

#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>

#define MW_SENSOR_NAME "mwsensor"

#define MW_SENSOR_NEAR 1
#define MW_SENSOR_FAR  2

// ioctl cmd
#define MW_SENSOR_IOC_MAGIC  'm'

#define MW_SENSOR_IOC_ENABLE _IOW(MW_SENSOR_IOC_MAGIC, 1, int)
#define MW_SENSOR_IOC_SET_RATE _IOW(MW_SENSOR_IOC_MAGIC, 2, int)

#define MW_SENSOR_IOC_MAXNR 2


struct mw_sensor_data {
   
    struct platform_device  *platform_dev;
    struct miscdevice       mw_sensor_device;
    struct input_dev        *input_dev;
    struct notifier_block   notifier;
    
    int                     irq;
    int                     irq_gpio;
    unsigned long           suspend_time;
    bool                    is_suspended;
    u32                     is_delay;
    u32                     is_poll;
    u32                     delay_time;
    bool                    enabled;
};

static inline uint32_t gettime_now(void)
{
   
	struct timeval tv;
	do_gettimeofday(&tv);
	return tv.tv_sec;
}

static void mw_sensor_report_event(struct mw_sensor_data *mw_sensor, s32 data)
{
   
    struct input_dev *input = mw_sensor->input_dev;

    if (!mw_sensor->enabled) {
   
        return;
    }

    input_report_rel(input, REL_MISC, data);
    input_sync(input);
}

static int mw_sensor_enable(struct mw_sensor_data *mw_sensor) {
   
    mw_sensor->enabled = true;
    if (gpio_get_value(mw_sensor->irq_gpio)) {
   
         mw_sensor_report_event(mw_sensor, MW_SENSOR_NEAR); 
    } else {
   
        mw_sensor_report_event(mw_sensor, MW_SENSOR_FAR); 
    }
    return 0;
}

static int mw_sensor_disable(struct mw_sensor_data *mw_sensor) {
   
    mw_sensor->enabled = false;
    return 0;
}

static int mw_sensor_suspend(struct mw_sensor_data *mw_sensor)
{
   
    dev_info(&mw_sensor->platform_dev->dev, "mw_sensor_suspend\n");
    mw_sensor->suspend_time = gettime_now();
    mw_sensor->is_suspended = true;
    //enable_irq_wake(mw_sensor->irq);
    
    return 0;
}

static int mw_sensor_resume(struct mw_sensor_data *mw_sensor)
{
   
    dev_info(&mw_sensor->platform_dev->dev, "mw_sensor_resume\n");
    //mw_sensor->is_suspended = false;
    //disable_irq_wake(mw_sensor->irq);

    return 0;
}

static int mw_sensor_fb_event_notify(struct notifier_block *noti,
                                     unsigned long event, void *data)
{
   
    int *blank;
    struct fb_event *ev_data = data;
    struct mw_sensor_data *mw_sensor = container_of(noti,
                                struct mw_sensor_data, notifier);

    if (ev_data && ev_data->data && event == FB_EVENT_BLANK && mw_sensor) {
   
        blank = ev_data->data;
        if (*blank == FB_BLANK_UNBLANK) {
   
            mw_sensor_resume(mw_sensor);
        } else if (*blank == FB_BLANK_POWERDOWN) {
   
            mw_sensor_suspend(mw_sensor);
        }
    }

    return NOTIFY_OK;
}

static void mw_sensor_wakeup(struct mw_sensor_data *mw_sensor) {
   
    dev_info(&mw_sensor->platform_dev->dev, "%s, wake up\n", __func__);
    
    input_report_key(mw_sensor->input_dev, KEY_POWER, 1);
    input_sync(mw_sensor->input_dev);
    input_report_key(mw_sensor->input_dev, KEY_POWER, 0);
    input_sync(mw_sensor->input_dev);
}

static irqreturn_t mw_sensor_irq_handle(int irq, void *dev_id)
{
   
    struct mw_sensor_data *mw_sensor = dev_id;
    unsigned long cur_time = gettime_now();

    // dts中配置是否延时,因为待机过程会产生干扰,导致微波Sensor误触发
    if (!mw_sensor->is_delay || abs(cur_time - mw_sensor->suspend_time) > mw_sensor->delay_time) {
   
        if (gpio_get_value(mw_sensor->irq_gpio)) {
   
            if (mw_sensor->is_suspended) {
   
                mw_sensor->is_suspended = false;
                mw_sensor_wakeup(mw_sensor);
                msleep(100);
                mw_sensor_report_event(mw_sensor, MW_SENSOR_NEAR);
            } else {
   
                mw_sensor_report_event(mw_sensor, MW_SENSOR_NEAR); 
            }
        } else {
   
            mw_sensor_report_event(mw_sensor, MW_SENSOR_FAR); 
        }
    }

    return IRQ_HANDLED;
}

static void mw_sensor_free_irq(struct mw_sensor_data *mw_sensor)
{
   
    if(mw_sensor) {
   
        free_irq(mw_sensor->irq, mw_sensor);
    }
}

static void mw_sensor_free_io_port(struct mw_sensor_data *mw_sensor)
{
   
    if(gpio_is_valid(mw_sensor->irq_gpio)) {
   
        gpio_free(mw_sensor->irq_gpio);
    }
    return;
}

static int mw_sensor_parse_dt(struct device *dev,
                              struct mw_sensor_data *mw_sensor)
{
   
    int ret = 0;
    struct device_node *np = dev->of_node;

    mw_sensor->irq_gpio = of_get_named_gpio(np, "irq-gpios", 0);
    if(!gpio_is_valid(mw_sensor->irq_gpio)) {
   
        dev_err(dev, "No valid irq gpio");
        return -1;
    }

    ret = of_property_read_u32(np, "mwsensor,is_delay", &mw_sensor->is_delay);
    if (ret) {
   
        mw_sensor->is_delay = 0;
    }

    ret = of_property_read_u32(np, "mwsensor,delay_time", &mw_sensor->delay_time);
    if (ret) {
   
        mw_sensor->delay_time = 3;
    }

    ret = of_property_read_u32(np, "mwsensor,is_poll",<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凉亭下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值