分类: LINUX
2013-04-26 11:10:18
输入子系统由驱动层、输入子系统核心、事件处理层三部分组成。一个输入事件,如鼠标移动、键盘按下等通过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
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include
15 #include
16 #include
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");
本文来自:http://www.cnblogs.com/myblesh/articles/2367648.html