linux输入子系统

来源:互联网 发布:php银联在线支付 编辑:程序博客网 时间:2024/05/01 09:39

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

 

 

 

 

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

 

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

 

 

 

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

 设备描述:

input_dev结构

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

 

注册输入设备函数:

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_dev是struct input_dev类型)

struct input_dev中有两个成员为:

evbit:

事件类型(包括

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

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\n",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\n",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 !!\n");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\n");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");
复制代码
0 0