瑞芯微Rockchip开发者社区
直播中

王敏

7年用户 1456经验值
私信 关注
[经验]

如何去实现RK3126人体感应模块驱动呢

其实人体感应模块驱动比较简单,就是一个GPIO口的检测,这里主要是想提供一个接口,给上层去比较容易的控制,一般我们可以写成JNI封装,我嫌太麻烦了,直接使用共享文件的方式,往/data/data/com.frame.cloud/mode.txt"下面写一个值,代表人体感应打开,另外一个值代表人体感应的关闭,内核和应用分别去监听文件的变化即可,比较简单,以下是驱动参考:

#include <dt-bindings/gpio/gpio.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/fb.h>
#include <linux/backlight.h>
#include <linux/err.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/termios.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>
#include <linux/input.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/hrtimer.h>
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/async.h>
#include <linux/input/mt.h>
#include <linux/wakelock.h>

static struct class *body_detect_class = NULL;
static struct input_dev *sinput_dev;
static struct timer_list gpio_timer;
static unsigned int time_delay = HZ * 1;
extern int lcd_enable ;
static unsigned int gpio_state = 0;
static int gpio3_d3;
static int body_detect_switch = 0;
static int irq_gpio3_d3;

#define BODY_DETECT_OPEN 300
#define BODY_DETECT_CLOSE 200

#define EYEMODE_FILENAME "/data/data/com.frame.cloud/mode.txt"

struct delayed_work read_body_switch_work;
static struct of_device_id gpio_of_match[] = {
{ .compatible = "body_det" },
{ }
};

MODULE_DEVICE_TABLE(of, gpio_of_match);

static int get_body_det_value(void)
{

struct file *fp;
mm_segment_t fs;
loff_t pos;
char buf[5];
int buf_len = 0;
fp =filp_open(EYEMODE_FILENAME,O_RDONLY,0);
if (IS_ERR(fp)){
    printk("open file error\n");
    return -1;
}

fs =get_fs();
set_fs(KERNEL_DS);
pos =0;
buf_len = vfs_read(fp,buf, sizeof(buf), &pos);
buf[buf_len] = '\0';
filp_close(fp,NULL);
set_fs(fs);

if(buf_len < 1)
{
    printk("can not get val from EYEMODE_FILENAME \n");
    return -1;
}
else
{
    return simple_strtol(buf,NULL,0);
}

}

static int gpio_statu_new = 1;
static int gpio_statu_pre = 1;
static void gpio_timer_func(unsigned long data)
{

gpio_state = gpio_get_value(gpio3_d3);
gpio_statu_new = gpio_state;

if (body_detect_switch == 0)
    return ;// not deal 

//printk("gpio_statu_new  = %d,gpio_statu_pre = %d\n",gpio_statu_new,gpio_statu_pre);
if(gpio_state == 0)
{
    if(lcd_enable == 0)
    {
        input_event(sinput_dev, EV_KEY, KEY_WAKEUP, 1);
        input_sync(sinput_dev);
        input_event(sinput_dev, EV_KEY, KEY_WAKEUP, 0);
        input_sync(sinput_dev);
        lcd_enable = 1;
    } 
    else
    {
        input_event(sinput_dev, EV_KEY, KEY_F1, 1);
        input_event(sinput_dev, EV_KEY, KEY_F1, 0);
        input_sync(sinput_dev);
    }
    
}

else if (gpio_state == 1)
{
    if(gpio_statu_new != gpio_statu_pre)
    {
        gpio_statu_pre = gpio_statu_new;
        input_event(sinput_dev, EV_KEY, KEY_F2, 1);
        input_event(sinput_dev, EV_KEY, KEY_F2, 0);
        input_sync(sinput_dev);
    }
}
mod_timer(&gpio_timer, jiffies +  time_delay);

}

static int init_timer_gpio(void)
{
init_timer(&gpio_timer);
gpio_timer.function = gpio_timer_func;
mod_timer(&gpio_timer, jiffies + HZ * 20 );
return 0;
}

static ssize_t body_det_switch_show(struct class *cls,struct class_attribute *attr, char *_buf)
{

printk("%s>>>>>>>> body_detect_switch = %d\n",__func__, body_detect_switch);
   ssize_t len = 0;
   len += snprintf(_buf + len, PAGE_SIZE - len, "%d \r\n", body_detect_switch);
   return 0;

}

static ssize_t body_det_switch_store(struct class *cls,struct class_attribute *attr, const char *buf, size_t _count)
{
body_detect_switch = simple_strtol(buf,NULL,10);

if( body_detect_switch == 1 || body_detect_switch == 0 )
    {                
            printk(KERN_INFO "body_detect_switch is %d\n",body_detect_switch);
    }
    else
    {
            body_detect_switch = -1;
            printk(KERN_INFO "body_detect_switch is not support\n");
    }

    return _count;

}

static CLASS_ATTR(body_det_switch, 0666, body_det_switch_show, body_det_switch_store);

static int body_det_sys_creat(void)
{
int ret ;
body_detect_class = class_create(THIS_MODULE, "body_det");
ret = class_create_file(body_detect_class, &class_attr_body_det_switch);
if (ret < 0)
{
class_destroy(body_detect_class);
body_detect_class = NULL;
printk("Fail to creat class body_detect_class.\n");
return -1;
}

return 0;
}

static int read_switch_function()
{
int body_det_value = -1;
body_det_value = get_body_det_value();

if(body_det_value == BODY_DETECT_OPEN)
{
    body_detect_switch = 1;
}else if (body_det_value == BODY_DETECT_CLOSE)
{
    body_detect_switch = 0;
}

}

static void read_body_switch_work_func( struct work_struct *work )
{
read_switch_function();
schedule_delayed_work(&read_body_switch_work, 10);
}

static int body_det_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = pdev->dev.of_node;
enum of_gpio_flags flags;
int ret;
int error;
struct proc_dir_entry *ent;
struct input_dev *input = NULL;

printk("func: %s\n", __func__); 
    if (!node)
            return -ENODEV;
    input = devm_input_allocate_device(dev);
    if (!input) {
        error = -ENOMEM;
        return error;
    }
    input->name = "body_detect";    /* pdev->name; */
    input->phys = "gpio-keys/input111";
    input->dev.parent = dev;
    input->id.bustype = BUS_HOST;
    input->id.vendor = 0x0001;
    input->id.product = 0x0001;
    input->id.version = 0x0100;
    error = input_register_device(input);
    if (error) {
        input_free_device(input);
        pr_err("gpio-keys: Unable to register input device, error: %d\n",error);
        return -EINVAL;
    }
    sinput_dev = input;
    input_set_capability(input, EV_KEY, KEY_F1);
    input_set_capability(input, EV_KEY, KEY_F2);
    input_set_capability(input, EV_KEY, KEY_WAKEUP);

    gpio3_d3 = of_get_named_gpio_flags(node, "body_det", 0, &flags);
    if(!gpio_is_valid(gpio3_d3)){
        dev_err(&pdev->dev, "invalid body_det gpio%d\n", gpio3_d3);
        return -EINVAL;
    }
    ret = devm_gpio_request(&pdev->dev, gpio3_d3, "body_det_gpio");
    if (ret) {
        dev_err(&pdev->dev,
            "failed to request GPIO%d for body_det_gpio\n",
            gpio3_d3);
        return -EINVAL;
    }
    gpio_direction_input(gpio3_d3);
    init_timer_gpio();

    ret = body_det_sys_creat();
    if(ret < 0)
    {
        printk("body_det_sys_creat failed \n");
        return -EINVAL;
    }
    INIT_DELAYED_WORK(&read_body_switch_work, read_body_switch_work_func);
    schedule_delayed_work(&read_body_switch_work, 10);
    return 0;

}

static int body_det_remove(struct platform_device *pdev)
{
return 0;
}

#ifdef CONFIG_PM_SLEEP
static int body_det_suspend(struct device *dev)
{
return 0;
}

static int body_det_resume(struct device *dev)
{
return 0;
}
#endif

static const struct dev_pm_ops body_det_ops = {
#ifdef CONFIG_PM_SLEEP
.suspend = body_det_suspend,
.resume = body_det_resume,
.poweroff = body_det_suspend,
.restore = body_det_resume,
#endif
};

static struct platform_driver gpio_driver = {
.driver = {
.name = "body_det",
.owner = THIS_MODULE,
.pm = &body_det_ops,
.of_match_table = of_match_ptr(gpio_of_match),
},
.probe = body_det_probe,
.remove = body_det_remove,
};

module_platform_driver(gpio_driver);

MODULE_DESCRIPTION("body_det");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:body_det");

原作者:botelv

更多回帖

发帖
×
20
完善资料,
赚取积分