zoukankan      html  css  js  c++  java
  • 和菜鸟一起学linux之input系统简单实例

           三伏天说来就来了,比起去年,今年的夏天没热得那么不可思议了。也许真正的炎热还没有到来。任时光匆匆而过,也没得到自己想要的生活方式,觉得有点得过且过的样子。需要换位思考,需要领悟人生的真谛,需要去追求自己想要的。觉得,孟非老师说的一句话很实在,工作再努力,提早完成了之后,能得到什么呢?只会换来领导的一句话,恩,不错,那个,那个这些事你也做一下吧。哈哈,的确如此,所以何不善待自己呢?做自己喜欢的事,而不是一味的工作,工作中虽然可以学到东西,但是,不可能只学一样啊,那样如果你想换换生活方式,换换工作,你又能做些什么呢?努力是需要的,我有我的梦想,我的未来,我的一切,合理安排时间,而不是把生活全部都放在了工作中,那样,岂不毁了一生,直待老去之后就只能慢慢懊悔,究竟得到了什么。。。。。。。。

           闲话讲了太多了,接下来还是回归正题吧。话说刚开始接触linux驱动时就是从char设备开始的,然后接着又把那个char设备改写为input设备了,从中也开始对于linux设备驱动编程入了个小门了接着就把那个代码贴一下,用以以后可以记起。

     

    具体的代码含义都加了注释了:

     

    #include <linux/slab.h>
    
    #include <linux/irq.h>
    
    #include <linux/interrupt.h>
    
    #include <linux/poll.h>
    
    #include <asm/io.h>
    
    #include <linux/delay.h>
    
    #include <linux/module.h>
    
    #include <linux/time.h>
    
    #include <linux/gpio.h>
    
    #include <linux/wait.h>
    
    #include <linux/input.h>
    
    #include <linux/init.h>
    
     
    
    static gpio_base = 96;       //gpio的基址,看不同的平台而定的。
    
    static pow_btn = 18;        //按键的中断号,也是依赖于平台的
    
     
    
    struct input_dev *btn_dev;      //input设备的结构体,这里定义了btn_dev
    
    struct delayed_work btn_work;    //这个是工作队列,用于让中断处理程序在中断后半部分
    
     
    
    static irqreturn_t power_isr(int irq, void *dev_id);  //中断入口函数
    
     
    
    static int __init button_init(void);         
    
    static void __exit button_exit(void);
    
     
    
    static void power_work_fn(struct work_struct *work)        //中断下半部分处理,即工作队列中处理
    
    {
    
        struct timeval tm_p, tm_n;
    
        unsigned char flag = 1;
    
        unsigned int width = 0;
    
        
    
        if(gpio_get_value(power)) return;
    
           
    
        do_gettimeofday(&tm_p);        //取当前的时间
    
        while(!gpio_get_value(pow_btn))   //判断按键是否弹起
    
        {
    
           if(!flag) continue;
    
           
    
           do_gettimeofday(&tm_n);        //再取间
    
            width = 1000000 * (tm_n.tv_sec - tm_p.tv_sec)    //计算两次的时间差,就是按键一直没弹起
    
                     + tm_n.tv_usec - tm_p.tv_usec;
    
           if(width >= 1500000)   //自己定义的超过了1.5s就上报一次,
    
           {
    
               input_report_key(btn_dev, KEY_POWER, 0);  //上报按键值
    
               input_report_key(btn_dev, KEY_POWER, 1);   
    
               input_sync(btn_dev);
    
               flag =0;
    
           }
    
        }
    
        
    
        if(flag)
    
        {
    
           input_report_key(btn_dev, KEY_POWER, 1);
    
            input_report_key(btn_dev, KEY_POWER, 0);
    
           input_sync(btn_dev);
    
        }
    
    }
    
     
    
    static irqreturn_t power_isr(int irq, void *dev_id)     //中断处理函数
    
    {
    
        schedule_delayed_work(&power_work, 0);      //把中断函数放在工作队列里去做了
    
        return IRQ_HANDLED;
    
    }
    
     
    
    static int __init button_init(void)
    
    {
    
        int error;
    
        gpio_request(pow_btn, "power-gpio");      //初始化申请gpio
    
        gpio_direction_input(pow_btn);            //设置gpio口为输入
    
     
    
        //申请中断
    
        if(reques_irq(gpio_base+pow_btn, power_isr, IRQ_DISABLED, "my_power", NULL) != 0)
    
        {
    
           printk(KERN_ERR "my_power: can't allocate irq %d\n", pow_btn);
    
            return (-EIO);
    
        }
    
         
    
        //分配input设备
    
        btn_dev = input_allocate_device();
    
        if(!btn_dev)
    
        {
    
           printk(KERN_ERR "button: not enough memory\n");
    
            error = -ENOMEM;
    
            goto err_free_irq;
    
        }
    
        
    
        //把相应的按键给置上
    
        btn_dev->evbit[0] = BIT_MASK(EV_KEY);
    
        btn_dev->keybit[BIT_WORK(KEY_POWER)] |= BIT_MASK(KEY_POWER);
    
        
    
        //注册input设备
    
        error = input_register_device(btn_dev);
    
        if(error)
    
        {
    
           printk(KERN_ERR "button: failed to register device\n");
    
            goto err_free_dev;
    
        }
    
           
    
        //初始化工作队列
    
        INIT_DELAYED_WORK(&power_work, power_work_fn);
    
     
    
        printk("$$$$$$$my_power button register ok\n");
    
        return 0;
    
     
    
    err_free_dev:
    
        input_free_device(btn_dev);
    
     
    
    err_free_irq:
    
        free_irq(gpio_base+pow_btn, power_isr);
    
     
    
        return error;    
    
    }
    
     
    
    static void __exit button_exit(void)
    
    {
    
        input_free_device(btn_dev);
    
        free_irq(gpio_base+pow_btn, power_isr);
    
    }
    
     
    
    module_init(button_init);
    
    module_exit(button_exit);
    
    MODULE_LICENSE("GPL");
    
    MODULE_AUTHOR("eastmoon");
    
     
    
    


     

     

            好了,这就是一个按键的设备驱动了,其中用到了很多知识了,像中断啊,input设备啊,工作队列啊,时间的获取啊。GPIO的使用啊。分析好了这个驱动,下面贴个应用层的调用。总不能只有个驱动,而没法测试吧。

     

     

     

    #include <stdio.h>
    
    #include <sys/ioctl.h>
    
    #include <unistd.h>
    
    #include <fcntl.h>
    
    #include <sys/types.h>
    
    #include <sys/stat.h>
    
    #include <sys/select.h>
    
    #include <sys/time.h>
    
    #include <linux/input.h>
    
     
    
    #define DEVICE "/dev/event0"
    
     
    
    int main(int argc, char *argv[])
    
    {
    
        struct input_event btn;
    
        int fd, rev;
    
        unsigned short type;
    
        unsigned short code;
    
        int value;
    
     
    
        fd = open(DEVICE, O_RDWR);
    
        if(fd < 0)
    
        {
    
            printf("Open file %s failed!\n", DEVICE);
    
            return -1;
    
        }
    
     
    
        while(1)
    
        {
    
         rev = read(fd, &btn, sizeof(struct input_event));
    
            if(rev > 0)
    
            {
    
                  type = btn.type;
    
                  code = btn.code;
    
                  value = btn.value;
    
                  printf("type = %d, code = %d, value = %d\n", type, code ,value);
    
            }
    
        }
    
        close(fd);
    
     
    
        return 0;
    
    }
    
     
    
    


        相比知道了上面的驱动程序,应用程序肯定显得那么简单了。就不多做分析了。

        这个就是最最简单的input的基本模型了,相信以这个为基础,其他的input设备也是大同小异的了。

  • 相关阅读:
    七牛php-sdk使用
    七牛php-sdk使用-多媒体处理
    七牛php-sdk使用-文档处理
    七牛php-sdk使用-文件上传
    php爬取微信文章内容
    php解决微信文章图片防盗链
    python2.7编译安装升级python3并安装Scrapy
    centos7安装配置supervisor守护进程
    vuejs+thinkphp5+phpsocketIO+timer数据及时更新
    docker常用命令
  • 原文地址:https://www.cnblogs.com/wuyida/p/6300075.html
Copyright © 2011-2022 走看看