輸入子系統由驅動層、輸入子系統核心、事件處理層三部分組成。一個輸入事件,如鼠標移動、鍵盤按下等通過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");