• 06day01input_driver


      1 /*
      2 输入子系统:
      3 把按键的驱动,添加到输入子系统中,可以通过按键来输入对应的字符
      4 
      5 内核中  include/linux/input.h 
      6 驱动中主要填充 input_dev 这个结构体
      7 name 名称  phys  uniq  input_id  设置对应的节点信息
      8 
      9 
     10 */
     11 #include <linux/module.h>
     12 #include <linux/init.h>
     13 #include <linux/kernel.h>
     14 
     15 #include <linux/input.h>
     16 #include <linux/bitops.h>
     17 #include <linux/interrupt.h> //request_irq
     18 #include <mach/irqs.h> //IRQ_EINT
     19 #include <linux/gpio.h>  //gpio_request
     20 #include <mach/gpio.h>  //EXYNOS4_GPX3
     21 /*
     22 用四个按键模拟键盘  把案件值 直接输出标准输出
     23 
     24 可以将开发板上的系统当前终端输入重定向为标准输入
     25 
     26 exec 0 < /dev/tty1
     27 */
     28 
     29 
     30 #define DEVNAME "ldm"
     31 
     32 //
     33 struct ldm_info
     34 {
     35     struct input_dev * pdev;
     36 };
     37 
     38 struct ldm_info ldm;
     39 
     40 struct  key_info
     41 {
     42     char * name;
     43     int code;
     44     int irqno;
     45     int gpio_num;
     46 };
     47 
     48 //l s enter   backspace
     49 struct key_info keyinfo[] = {
     50     {"KEY_L", KEY_L, IRQ_EINT(26), EXYNOS4_GPX3(2)},
     51     {"KEY_S", KEY_S, IRQ_EINT(27), EXYNOS4_GPX3(3)},
     52     {"KEY_ENTER", KEY_ENTER, IRQ_EINT(28), EXYNOS4_GPX3(4)},
     53     {"KEY_BACKSPACE", KEY_BACKSPACE, IRQ_EINT(29), EXYNOS4_GPX3(5)},  
     54 };
     55 
     56 //中断处理函数
     57 static irqreturn_t key_handler(int irqno, void * arg)
     58 {
     59     struct key_info *key = (struct key_info *)arg;
     60     //产生了中断,在合适时候,发送input_event事件
     61 
     62     int key_stat = gpio_get_value(key->gpio_num);
     63 
     64     //发送事件  发送按键的按键值 和 按键的状态
     65     input_report_key(ldm.pdev,  key->code,  !key_stat);
     66     //发送结束事件
     67     input_sync(ldm.pdev);
     68 
     69     return IRQ_HANDLED;
     70 }
     71 
     72 static int test_init(void)
     73 {
     74     int ret = 0;
     75     int i = 0;
     76     int j = 0;
     77     printk("%s:%s:%d
    ", __FILE__, __FUNCTION__, __LINE__);
     78 
     79     //1.创建input_dev 的对象  input_allocate_device();
     80     //如果仅仅申请了空间,没有注册 即调用input_allocate_device
     81     //那么需要调用input_free_device 函数来释放空间
     82     //一旦注册成功,则不需要调用input_free_device来释放空间
     83     ldm.pdev = input_allocate_device();
     84     if(!ldm.pdev) {
     85         printk("input_allocate_device  failed
    ");
     86         ret = -ENOMEM;
     87         goto err_input_allocate_device;
     88     }
     89 
     90     //2.填充input_dev 这个结构体
     91     ////////////相关的信息/////////////////////////
     92     ldm.pdev->name = "my test input device";
     93     ldm.pdev->phys = "key";
     94     ldm.pdev->uniq = "candle";
     95     ldm.pdev->id.bustype = 0x1234;
     96     ldm.pdev->id.vendor = 0x2222;
     97     ldm.pdev->id.product =  0xabcd;
     98     ldm.pdev->id.version =  0x3433;
     99     ///////////////////////////////////////////////////////
    100 
    101     //这个设备支持哪些事件?
    102     //本设备支持的事件的类型,通过set_bit函数来指定位置
    103     //所有的位置,都可以通过宏来设置
    104     set_bit(EV_KEY,   ldm.pdev->evbit); //支持按键类型的事件
    105     set_bit(EV_REP, ldm.pdev->evbit);//支持连发
    106 
    107     //针对不同的事件,处理什么样的数据?
    108     //eint26~29   GPX3_2 ~5
    109     //这个设备支持的按键的键值
    110     
    111     for(i=0; i< ARRAY_SIZE(keyinfo);i++) {
    112         set_bit(keyinfo[i].code, ldm.pdev->keybit);
    113     }
    114 
    115     //注册设备对象
    116     ret = input_register_device(ldm.pdev);
    117     if(ret < 0) {
    118         printk("input_register_device  failed
    ");
    119         goto  err_input_register_device;
    120     }
    121 
    122     //注册中断,按下和抬起的时候都要去触发
    123     for(i=0;i < ARRAY_SIZE(keyinfo);i++) {
    124         ret = request_irq(keyinfo[i].irqno, key_handler, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, DEVNAME, keyinfo + i );
    125         if(ret < 0) {
    126             printk("request_irq  failed
    ");
    127             goto err_request_irq;
    128         }
    129     }
    130 
    131     //注册GPIO管脚
    132     //int j = 0;
    133     for(j=0; j < ARRAY_SIZE(keyinfo);j++) {
    134         ret = gpio_request(keyinfo[j].gpio_num, keyinfo[j].name);
    135         if(ret < 0) {
    136             printk("gpio_request  failed
    ");
    137             goto err_gpio_request;
    138         }
    139     }
    140 
    141 
    142     return 0;
    143 
    144 err_gpio_request:
    145     for(j = j - 1;j>=0;j--) {
    146         gpio_free(keyinfo[j].gpio_num);
    147     }
    148 err_request_irq:
    149     for(i=i-1;i>=0;i--) {
    150         free_irq(keyinfo[i].irqno, keyinfo + i); 
    151         //把之前注册成功的中断号释放掉
    152     }
    153     input_unregister_device(ldm.pdev);
    154     return ret;
    155 err_input_register_device:
    156     input_free_device(ldm.pdev);
    157 err_input_allocate_device:
    158     return ret;
    159 }
    160 
    161 static  void test_exit(void)
    162 {
    163     int i = ARRAY_SIZE(keyinfo);
    164     printk("%s:%s:%d
    ", __FILE__, __FUNCTION__, __LINE__);
    165     
    166 
    167     for(i=i-1; i>=0;i--) {
    168         gpio_free(keyinfo[i].gpio_num);
    169         free_irq(keyinfo[i].irqno, keyinfo + i);
    170     }
    171 
    172     input_unregister_device(ldm.pdev);
    173 }
    174 
    175 
    176 module_init(test_init);
    177 module_exit(test_exit);
    178 MODULE_LICENSE("GPL");
  • 相关阅读:
    pythonchallenge 解谜 Level 6
    pythonchallenge 解谜 Level 5
    pythonchallenge 解谜 Level 4
    pythonchallenge 解谜 Level 3
    pythonchallenge 解谜 Level 2
    pythonchallenge 解谜 Level 1
    CCF 201912-2 回收站选址
    JavaWeb+JDBC+Servlet+SqlServer实现登录功能
    后台连接数据库的方法
    jQuery实现轮播图
  • 原文地址:https://www.cnblogs.com/baoshulin/p/6477030.html
Copyright © 2020-2023  润新知