您的位置:首页 > 运维架构 > Linux

【转】LINUX设备驱动之输入子系统(三)

2011-08-24 16:15 351 查看
Eric Fang 2010-02-04

--------------------------------------------------------------

本站分析linux内核源码,版本号为2.6.32.3

转载请注明出处:http://ericfang.cublog.cn/

--------------------------------------------------------------

接上一篇文章继续分析。

三.input_event事件的处理

事件的处理的接口函数为input_event,在\linux\input.h中还定义了、 input_report_key、input_report_rel、input_report_abs、input_report_ff_status、input_report_switch、input_sync、input_mt_sync等函数,这些函数都是input_event函数的封装,用于下层驱动向输入子系统上报事件,另外input_inject_event函数用于输入子系统向设备产生事件。

input_event函数定义如下:

0302 void input_event(struct input_dev *dev,

0303 unsigned int type, unsigned int code, int value)

0304 {

0305 unsigned long flags;

0306

0307 if (is_event_supported(type, dev->evbit, EV_MAX)) {

0308

0309 spin_lock_irqsave(&dev->event_lock, flags);

0310 add_input_randomness(type, code, value);

0311 input_handle_event(dev, type, code, value);

0312 spin_unlock_irqrestore(&dev->event_lock, flags);

0313 }

0314 }

先看看第0307行的判断:

0065 static inline int is_event_supported(unsigned int code,

0066 unsigned long *bm, unsigned int max)

0067 {

0068 return code <= max && test_bit(code, bm);

0069 }

判断事件是否合法,即dev->evbit是否定义了type位。

如果is_event_supported返回非0则先去获得dev->event_lock自旋锁并关中断,第0310与系统的随机因子有关,这里不讨论,接着转入0311行input_handle_event函数:

0165 static void input_handle_event(struct input_dev *dev,

0166 unsigned int type, unsigned int code, int value)

0167 {

0168 int disposition = INPUT_IGNORE_EVENT;

0169

0170 switch (type) {

0171

0172 case EV_SYN:

0173 switch (code) {

0174 case SYN_CONFIG:

0175 disposition = INPUT_PASS_TO_ALL;

0176 break;

0177

0178 case SYN_REPORT:

0179 if (!dev->sync) {

0180 dev->sync = 1;

0181 disposition = INPUT_PASS_TO_HANDLERS;

0182 }

0183 break;

0184 case SYN_MT_REPORT:

0185 dev->sync = 0;

0186 disposition = INPUT_PASS_TO_HANDLERS;

0187 break;

0188 }

0189 break;

0190

0191 case EV_KEY:

0192 if (is_event_supported(code, dev->keybit, KEY_MAX) &&

0193 !!test_bit(code, dev->key) != value) {

0194

0195 if (value != 2) {

0196 __change_bit(code, dev->key);

0197 if (value)

0198 input_start_autorepeat(dev, code);

0199 else

0200 input_stop_autorepeat(dev);

0201 }

0202

0203 disposition = INPUT_PASS_TO_HANDLERS;

0204 }

0205 break;

0206

0207 case EV_SW:

0208 if (is_event_supported(code, dev->swbit, SW_MAX) &&

0209 !!test_bit(code, dev->sw) != value) {

0210

0211 __change_bit(code, dev->sw);

0212 disposition = INPUT_PASS_TO_HANDLERS;

0213 }

0214 break;

0215

0216 case EV_ABS:

0217 if (is_event_supported(code, dev->absbit, ABS_MAX)) {

0218

0219 if (test_bit(code, input_abs_bypass)) {

0220 disposition = INPUT_PASS_TO_HANDLERS;

0221 break;

0222 }

0223

0224 value = input_defuzz_abs_event(value,

0225 dev->abs[code], dev->absfuzz[code]);

0226

0227 if (dev->abs[code] != value) {

0228 dev->abs[code] = value;

0229 disposition = INPUT_PASS_TO_HANDLERS;

0230 }

0231 }

0232 break;

0233

0234 case EV_REL:

0235 if (is_event_supported(code, dev->relbit, REL_MAX) && value)

0236 disposition = INPUT_PASS_TO_HANDLERS;

0237

0238 break;

0239

0240 case EV_MSC:

0241 if (is_event_supported(code, dev->mscbit, MSC_MAX))

0242 disposition = INPUT_PASS_TO_ALL;

0243

0244 break;

0245

0246 case EV_LED:

0247 if (is_event_supported(code, dev->ledbit, LED_MAX) &&

0248 !!test_bit(code, dev->led) != value) {

0249

0250 __change_bit(code, dev->led);

0251 disposition = INPUT_PASS_TO_ALL;

0252 }

0253 break;

0254

0255 case EV_SND:

0256 if (is_event_supported(code, dev->sndbit, SND_MAX)) {

0257

0258 if (!!test_bit(code, dev->snd) != !!value)

0259 __change_bit(code, dev->snd);

0260 disposition = INPUT_PASS_TO_ALL;

0261 }

0262 break;

0263

0264 case EV_REP:

0265 if (code <= REP_MAX && value >= 0 && dev->rep[code] != value) {

0266 dev->rep[code] = value;

0267 disposition = INPUT_PASS_TO_ALL;

0268 }

0269 break;

0270

0271 case EV_FF:

0272 if (value >= 0)

0273 disposition = INPUT_PASS_TO_ALL;

0274 break;

0275

0276 case EV_PWR:

0277 disposition = INPUT_PASS_TO_ALL;

0278 break;

0279 }

0280

0281 if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)

0282 dev->sync = 0;

0283

0284 if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)

0285 dev->event (dev, type, code, value);

0286

0287 if (disposition & INPUT_PASS_TO_HANDLERS)

0288 input_pass_event(dev, type, code, value);

0289 }

第0168~0279根据输入参数type,和code设置disposition的值,disposition的值为下列四种情况之一:

0160 #define INPUT_IGNORE_EVENT 0

忽略事件;

0161 #define INPUT_PASS_TO_HANDLERS 1

事件需要handler来处理;

0162 #define INPUT_PASS_TO_DEVICE 2

事件需要device来处理;

0163 #define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)

事件同时需要handler和device来处理

接着0284~0288行根据disposition的值选择执行dev->event和input_pass_event函数。

首先看0285行这个event回调函数,对于atkbd键盘驱动,在注册input_dev时有下列语句:

input_dev->event = atkbd_event;

atkbd_event函数如下:

0624 static int atkbd_event(struct input_dev *dev,

0625 unsigned int type, unsigned int code, int value)

0626 {

0627 struct atkbd *atkbd = input_get_drvdata(dev);

0628

0629 if (!atkbd->write)

0630 return -1;

0631

0632 switch (type) {

0633

0634 case EV_LED:

0635 atkbd_schedule_event_work(atkbd, ATKBD_LED_EVENT_BIT);

0636 return 0;

0637

0638 case EV_REP:

0639 if (!atkbd->softrepeat)

0640 atkbd_schedule_event_work(atkbd, ATKBD_REP_EVENT_BIT);

0641 return 0;

0642 }

0643

0644 return -1;

0645 }

第0629行如果设备不支持往设备写操作,则返回-1。

第0634行如果type为EV_LED类型事件,则调用atkbd_schedule_event_work函数:

0605 static void atkbd_schedule_event_work(struct atkbd *atkbd, int event_bit)

0606 {

0607 unsigned long delay = msecs_to_jiffies(50);

0608

0609 if (time_after(jiffies, atkbd->event_jiffies + delay))

0610 delay = 0;

0611

0612 atkbd->event_jiffies = jiffies;

0613 set_bit(event_bit, &atkbd->event_mask);

0614 wmb();

0615 schedule_delayed_work(&atkbd->event_work, delay);

0616 }

这个函数会在delay一定时间后激活atkbd的event_work进程,这个进程会告诉设备闪烁led等待或设置重复延迟时间。如果你有兴趣可以参考\drivers\input\keyboard\ atkbd.c中相关代码。

接着看input_handle_event函数第0288行,调用handler处理的函数input_pass_event:

0091 static void input_pass_event(struct input_dev *dev,

0092 unsigned int type, unsigned int code, int value)

0093 {

0094 struct input_handle *handle;

0095

0096 rcu_read_lock();

0097

0098 handle = rcu_dereference(dev->grab);

0099 if (handle)

0100 handle->handler->event(handle, type, code, value);

0101 else

0102 list_for_each_entry_rcu(handle, & dev->h_list, d_node)

0103 if (handle->open)

0104 handle->handler->event(handle,

0105 type, code, value);

0106 rcu_read_unlock();

0107 }

第0098~0105行,如果input_dev指定了handle,则调用该指向handler的event函数,否则遍历input_dev的h_list上的handle,在前面handle注册的分析中已经知道handle挂到input_dev的h_list链表上。这里要强调一点:dev->h_list上所有的handle,只要其open字段不为0,就会执行其handle->handler->event函数。对于kbd_handler相应的event函数为kbd_event,看一下这个函数:

1296 static void kbd_event(struct input_handle *handle, unsigned int event_type,

1297 unsigned int event_code, int value)

1298 {

1299 if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))

1300 kbd_rawcode(value);

1301 if (event_type == EV_KEY)

1302 kbd_keycode(event_code, value, HW_RAW(handle->dev));

1303 tasklet_schedule(&keyboard_tasklet);

1304 do_poke_blanked_console = 1;

1305 schedule_console_callback();

1306 }

根据event_type的值调用kbd_rawcode和kbd_keycode,然后调度keyboard_tasklet tasklet,接着调用schedule_console_callback函数,这部分涉及到tty的内容,等后面分析tty驱动时再进一步分析这部分。

四.输入子系统的初始化

到这里,已经基本清楚了输入子系统的结构了,但还有一个疑点,在注册handler函数input_register_handler中的下列代码片段中:

1611 if (handler->fops != NULL) {

1612 if (input_table[handler->minor >> 5]) {

1613 retval = -EBUSY;

1614 goto out;

1615 }

1616 input_table[handler->minor >> 5] = handler;

1617 }

这个input_table数组有什么作用呢?要明白这点得从输入子系统的初始化讲起,初始化函数如下:

1779 static int __init input_init(void)

1780 {

1781 int err;

1782

1783 input_init_abs_bypass();

1784

1785 err = class_register(&input_class);

1786 if (err) {

1787 printk(KERN_ERR "input: unable to register input_dev class\n");

1788 return err;

1789 }

1790

1791 err = input_proc_init();

1792 if (err)

1793 goto fail1;

1794

1795 err = register_chrdev(INPUT_MAJOR, "input", &input_fops);

1796 if (err) {

1797 printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);

1798 goto fail2;

1799 }

1800

1801 return 0;

1802

1803 fail2: input_proc_exit();

1804 fail1: class_unregister(&input_class);

1805 return err;

1806 }

第1785行注册了一个名为”input”的类,所有input device都属于这个类,在sysfs中,所有input device的目录都位于/dev/class/input下面。

第1791在/proc下面建立相关的交互文件:

0965 static int __init input_proc_init(void)

0966 {

0967 struct proc_dir_entry *entry;

0968

0969 proc_bus_input_dir = proc_mkdir("bus/input", NULL);

0970 if (!proc_bus_input_dir)

0971 return -ENOMEM;

0972

0973 entry = proc_create("devices", 0, proc_bus_input_dir,

0974 &input_devices_fileops);

0975 if (!entry)

0976 goto fail1;

0977

0978 entry = proc_create("handlers", 0, proc_bus_input_dir,

0979 &input_handlers_fileops);

0980 if (!entry)

0981 goto fail2;

0982

0983 return 0;

0984

0985 fail2: remove_proc_entry("devices", proc_bus_input_dir);

0986 fail1: remove_proc_entry("bus/input", NULL);

0987 return -ENOMEM;

0988 }

第1795行,调用register_chrdev函数注册了主设备号为INPUT_MAJOR(即13)次设备号为0~255的字符设备。其文件操作指针为input_fops,也即主设备号为13的设备的文件操作指针为input_fops,其定义如下:

1766 static const struct file_operations input_fops = {

1767 .owner = THIS_MODULE,

1768 .open = input_open_file,

1769 };

看一下这个open函数:

1728 static int input_open_file(struct inode *inode, struct file *file)

1729 {

1730 struct input_handler *handler;

1731 const struct file_operations *old_fops, *new_fops = NULL;

1732 int err;

1733

1734 lock_kernel();

1735 /* No load-on-demand here? */

1736 handler = input_table[iminor(inode) >> 5];

1737 if (!handler || !(new_fops = fops_get(handler->fops))) {

1738 err = -ENODEV;

1739 goto out;

1740 }

1741

1742 /*

1743 * That's _really_ odd. Usually NULL ->open means "nothing special",

1744 * not "no device". Oh, well...

1745 */

1746 if (!new_fops->open) {

1747 fops_put(new_fops);

1748 err = -ENODEV;

1749 goto out;

1750 }

1751 old_fops = file->f_op;

1752 file->f_op = new_fops;

1753

1754 err = new_fops->open(inode, file);

1755

1756 if (err) {

1757 fops_put(file->f_op);

1758 file->f_op = fops_get(old_fops);

1759 }

1760 fops_put(old_fops);

1761 out:

1762 unlock_kernel();

1763 return err;

1764 }

第1736行,看到我们熟悉的input_table数组了,其定义如下:

0063 static struct input_handler *input_table[8];

输入子系统把主设备号为13的256个次设备号分成8组,每组对应一个input_handler,存放在input_table数组中,现在我们可以理解上面的代码片段了:当注册input_handler时,如果其fops指针不为NULL,就会分下列两种情况:1,input_table数组中相应索引的元素还没指向某个input_handler,则将其指向这个input_handler,2,nput_table数组中相应索引的元素已经指向某个input_handler,则不会注册这个input_handler。

继续看input_open_file函数,获得设备号inode对应的handler后,如果其fops->open不为空,则会改变相应文件的f_op指针,将其指向该open,然后调用它,如果open返回非0,就会恢复相应文件的f_op指针并返回不能成功打开文件。

小结:输入子系统到这里就全部分析完了,本次在分析过程中以at键盘驱动为例子,如果你还想了解更多更深入,可以去阅读内核的evdev模块,其对应的input_handler匹配了所有的input device,代码位于\drivers\input\evdev.c中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: