zoukankan      html  css  js  c++  java
  • linux输入子系统


    输入子系统由驱动层、输入子系统核心、事件处理层三部分组成。一个输入事件,如鼠标移动、键盘按下等通过Driver->Inputcore->Event handler->userspace的顺序到达用户控件的应用程序。

     

     

     

     

    驱动层:将底层的硬件输入转化为统一事件形式,想输入核心(Input Core)汇报。

     

    输入子系统核心:承上启下。为驱动层提供输入设备注册与操作接口,如:input_register_device;通知事件处理层对事件进行处理;在/Proc下产生相应的设备信息

     

     

     

    事件处理层:主要是和用户空间交互。(Linux中在用户空间将所有的设备都当初文件来处理,由于在一般的驱动程序中都有提供fops接口,以及在/dev下生成相应的设备文件nod,这些操作在输入子系统中由事件处理层完成)

     设备描述:

    input_dev结构

     实现设备驱动核心工作是:向系统报告按键、触摸屏等输入事件(event,通过input_event结构描述),不再需要关心文件操作接口。驱动报告事件经过inputCoreEventhandler到达用户空间。

     

    注册输入设备函数:

    int input_register_device(struct input_dev *dev)

     

    注销输入设备函数:

    void input_unregister_device(struct input_dev *dev)

     

    驱动实现——初始化(事件支持)

    set_bit()告诉input输入子系统支持哪些事件,哪些按键。例如:

     

    set_bit(EV_KEY,button_dev.evbit)  (其中button_devstruct input_dev类型)

    struct input_dev中有两个成员为:

    evbit:

    事件类型(包括

    EV_RST,EV_REL,EV_MSC,EV_KEY,EV_ABS,EV_REP等)

    Linux中输入设备的事件类型有(这里只列出了常用的一些,更多请看linux/input.h中):
    我:
    EV_SYN 同步事件
    EV_KEY 键盘事件
    EV_REL 相对坐标事件,用于鼠标
    EV_ABS 绝对坐标事件,用于摇杆
    EV_MSC 其他事件
    EV_LED LED灯事件
    EV_SND 声音事件
    EV_REP 重复按键事件
    EV_FF 受力事件
    EV_PWR 电源事件
    EV_FF_STATUS 受力状态事件

    keybit:

    按键类型(当事件类型为EV_KEY时包括

    BTN_LEFT,BTN_0,BTN_1,BTN_MIDDLE等)

     

    驱动实现——报告事件:

    用于报告EV_KEY,EV_REL,EV_ABS事件的函数分别为void input_report_key(struct

      input_dev *dev,unsigned int code,int value)

    void input_report_rel(struct

      input_dev *dev,unsigned int code,int value)

    void input_report_abs(struct

      input_dev *dev,unsigned int code,int value)

     

    驱动实现——报告结束:

    input_sync()同步用于告诉input core子系统报告结束。

     

    实例:触摸屏设备驱动中,一次点击的整个报告过程如下:

    input_reprot_abs(input_dev,ABS_X,x);   //x坐标

    input_reprot_abs(input_dev,ABS_Y,y);   // y坐标

    input_reprot_abs(input_dev,ABS_PRESSURE,1);

    input_sync(input_dev);//同步结束

     

     

    实例分析(按键中断程序):

    //按键初始化

    static int __init button_init(void)

    {//申请中断

    if(request_irq(BUTTON_IRQ,button_interrupt,0,”button”,NUll))

          return –EBUSY;

    set_bit(EV_KEY,button_dev.evbit); //支持EV_KEY事件

     

    set_bit(BTN_0,button_dev.keybit); //支持设备两个键

     

    set_bit(BTN_1,button_dev.keybit); //

     

    input_register_device(&button_dev);//注册input设备

    }

    /*在按键中断中报告事件*/

    Static void button_interrupt(int irq,void *dummy,struct pt_regs *fp)

    {

    input_report_key(&button_dev,BTN_0,inb(BUTTON_PORT0));//读取寄存器BUTTON_PORT0的值

    input_report_key(&button_dev,BTN_1,inb(BUTTON_PORT1));

    input_sync(&button_dev);

    }

    总结:input子系统仍然是字符设备驱动程序,但是代码量减少很多,input子系统只需要完成两个工作:初始化和事件报告(这里在linux中是通过中断来实现的)。读者不妨用sourceinsignt 输入input_init去搜关于输入子系统的实现

     

    实例:

    复制代码
      1 #include <linux/module.h>
      2 #include <linux/kernel.h>
      3 #include <linux/fs.h>
      4 #include <linux/init.h>
      5 #include <linux/delay.h>
      6 #include <linux/poll.h>
      7 #include <linux/irq.h>
      8 #include <asm/irq.h>
      9 #include <linux/interrupt.h>
     10 #include <asm/uaccess.h>
     11 #include <mach/regs-gpio.h>
     12 #include <mach/hardware.h>
     13 #include <linux/platform_device.h>
     14 #include <linux/cdev.h>
     15 #include <linux/miscdevice.h>
     16 #include <linux/input.h>
     17 
     18 struct input_dev *button_dev;
     19 struct button_irq_desc {
     20     int irq;
     21     int pin;
     22     int pin_setting;
     23     int number;
     24     char *name;    
     25 };
     26 
     27 /*定义一个结构体数组*/
     28 static struct button_irq_desc button_irqs [] = {
     29     {IRQ_EINT8 , S3C2410_GPG0 ,  S3C2410_GPG0_EINT8  , 0, "KEY0"},  
     30     {IRQ_EINT11, S3C2410_GPG3 ,  S3C2410_GPG3_EINT11 , 1, "KEY1"},
     31     {IRQ_EINT13, S3C2410_GPG5 ,  S3C2410_GPG5_EINT13 , 2, "KEY2"},
     32     {IRQ_EINT14, S3C2410_GPG6 ,  S3C2410_GPG6_EINT14 , 3, "KEY3"},
     33     {IRQ_EINT15, S3C2410_GPG7 ,  S3C2410_GPG7_EINT15 , 4, "KEY4"},
     34     {IRQ_EINT19, S3C2410_GPG11,  S3C2410_GPG11_EINT19, 5, "KEY5"},
     35 };
     36 
     37 static int key_values = 0;
     38 
     39 static irqreturn_t buttons_interrupt(int irq, void *dev_id)
     40 {
     41     struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;
     42     int down;
     43      udelay(0);
     44      /*获取按键值*/
     45     down = !s3c2410_gpio_getpin(button_irqs->pin);   //down: 1(按下),0(弹起)
     46    if (!down) { 
     47     
     48     /*报告事件*/
     49     key_values = button_irqs->number;
     50     //printk("====>rising key_values=%d
    ",key_values);
     51   if(key_values==0)
     52       input_report_key(button_dev, KEY_1, 0);
     53   if(key_values==1)
     54       input_report_key(button_dev, KEY_2, 0);
     55   if(key_values==2)
     56       input_report_key(button_dev, KEY_3, 0);
     57   if(key_values==3)
     58       input_report_key(button_dev, KEY_4, 0);
     59   if(key_values==4)
     60       input_report_key(button_dev, KEY_5, 0);
     61   if(key_values==5)
     62       input_report_key(button_dev, KEY_6, 0);
     63   /*报告结束*/
     64   input_sync(button_dev);      
     65         }
     66   
     67    else {
     68      
     69         key_values = button_irqs->number;
     70         //printk("====>falling key_values=%d
    ",key_values);
     71   if(key_values==0)
     72         input_report_key(button_dev, KEY_1, 1);
     73   if(key_values==1)
     74         input_report_key(button_dev, KEY_2, 1);
     75   if(key_values==2)
     76         input_report_key(button_dev, KEY_3, 1);
     77   if(key_values==3)
     78         input_report_key(button_dev, KEY_4, 1);
     79   if(key_values==4)
     80         input_report_key(button_dev, KEY_5, 1);
     81   if(key_values==5)
     82         input_report_key(button_dev, KEY_6, 1);
     83   input_sync(button_dev);      
     84 
     85      }
     86 
     87   
     88     return IRQ_RETVAL(IRQ_HANDLED);
     89 }
     90 
     91 
     92 static int s3c24xx_request_irq(void)
     93 {
     94     int i;
     95     int err = 0;
     96     
     97     for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {
     98     
     99 
    100                 if (button_irqs[i].irq < 0) {
    101                                 continue;
    102                     }
    103      /* IRQ_TYPE_EDGE_FALLING,IRQ_TYPE_EDGE_RISING,IRQ_TYPE_EDGE_BOTH */
    104         err = request_irq(button_irqs[i].irq, buttons_interrupt, IRQ_TYPE_EDGE_BOTH, 
    105                           button_irqs[i].name, (void *)&button_irqs[i]);
    106         if (err)
    107             break;
    108     }
    109 /*错误处理*/
    110     if (err) {
    111         i--;
    112         for (; i >= 0; i--) {
    113         if (button_irqs[i].irq < 0) {
    114         continue;
    115         }
    116         disable_irq(button_irqs[i].irq);
    117             free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);
    118         }
    119         return -EBUSY;
    120     }
    121 
    122     
    123     return 0;
    124 }
    125 
    126 
    127 static int __init dev_init(void)
    128 {
    129 
    130   
    131   /*request irq*/
    132   s3c24xx_request_irq();
    133     /* Initialise input stuff */
    134     button_dev = input_allocate_device();
    135     if (!button_dev) {
    136         printk(KERN_ERR "Unable to allocate the input device !!
    ");
    137         return -ENOMEM;
    138     }
    139     button_dev->name = "s3c2440_button";
    140     button_dev->id.bustype = BUS_RS232;
    141   button_dev->id.vendor = 0xDEAD;
    142   button_dev->id.product = 0xBEEF;
    143   button_dev->id.version = 0x0100;
    144 
    145     button_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT(EV_SYN);
    146     //set_bit(EV_KEY, button_dev->evbit)//支持EV_KEY事件
    147      /*设置支持哪些按键*/
    148     set_bit(KEY_1,   button_dev->keybit);
    149     set_bit(KEY_2,   button_dev->keybit);
    150     set_bit(KEY_3,   button_dev->keybit);
    151     set_bit(KEY_4,   button_dev->keybit);
    152     set_bit(KEY_5,   button_dev->keybit);
    153     set_bit(KEY_6,   button_dev->keybit);
    154     //printk("KEY_RESERVED=%d ,KEY_1=%d",KEY_RESERVED,KEY_1);
    155     input_register_device(button_dev);   //注册input设备
    156 
    157     printk ("initialized
    ");
    158 
    159     return 0;
    160 }
    161 
    162 static void __exit dev_exit(void)
    163 {
    164         int i;
    165     
    166   for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {
    167         if (button_irqs[i].irq < 0) {
    168             continue;
    169             }
    170         free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);
    171    }
    172 
    173     input_unregister_device(button_dev);
    174 }
    175 
    176 module_init(dev_init);
    177 module_exit(dev_exit);
    178 MODULE_LICENSE("GPL");
    179 MODULE_AUTHOR("David Xie");
    复制代码

  • 相关阅读:
    PHP 函数
    MariaDB——(三) MariaDB 10.0.15 standard replication主从复制搭建
    MariaDB——(二) MariaDB 10.0.15 日志文件—undo 日志
    MariaDB——(一)CentOS 6.5 下 MariaDB 10.0.15 YUM 安装
    虚拟机中的linux系统文件突然全部变成只读的问题
    复制虚拟机vmware centos搭建集群节点过程中网络配置eth0和eth1遇到的问题以及NAT模式下虚拟机静态IP配置方法
    WMware 中CentOS系统Hadoop 分布式环境搭建(一)——Hadoop安装环境准备
    关于Oracle字符集在dmp文件导入导出中的乱码影响
    VMware 打开虚拟机的时候提示 internal error 内部错误 遇到这个问题时我的解决方法
    ORACLE 存储过程中保存用户自定义异常信息的一种方式
  • 原文地址:https://www.cnblogs.com/muhuacat/p/8028961.html
Copyright © 2011-2022 走看看