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等)

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去搜關於輸入子系統的實現

 

實例:

View Code
  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");

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM