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

李明聪

7年用户 1155经验值
私信 关注
[问答]

RK3126人体感应模块驱动分享,错过绝对后悔

RK3126人体感应模块驱动分享,错过绝对后悔

回帖(1)

欧建杭

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

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

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 errorn");
        return -1;
    }

    fs =get_fs();
    set_fs(KERNEL_DS);
    pos =0;
    buf_len = vfs_read(fp,buf, sizeof(buf), &pos);
    buf[buf_len] = '';
    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 = %dn",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 = %dn",__func__, body_detect_switch);
       ssize_t len = 0;
       len += snprintf(_buf + len, PAGE_SIZE - len, "%d rn", 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 %dn",body_detect_switch);
        }
        else
        {
                body_detect_switch = -1;
                printk(KERN_INFO "body_detect_switch is not supportn");
        }

        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: %sn", __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: %dn",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%dn", 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_gpion",
                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");


举报

更多回帖

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