免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1395 | 回复: 0
打印 上一主题 下一主题

Linux设备模型之input子系统详解 2 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-09-17 18:11 |只看该作者 |倒序浏览
handler->name, kobject_name(&dev->dev.kobj), error); return error;}如 果handle的blacklist被赋值。要先匹配blacklist中的数据跟dev->id的数据是否匹配。匹配成功过后再来匹配 handle->id和dev->id中的数据。如果匹配成功,则调用handler->connect().来看一下具体的数据匹配过程,这是在input_match_device()中完成的。代码如下:static const struct input_device_id *input_match_device(const struct input_device_id *id, struct input_dev *dev){ int i; for (; id->flags || id->driver_info; id++) { if (id->flags & INPUT_DEVICE_ID_MATCH_BUS) if (id->bustype != dev->id.bustype) continue; if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR) if (id->vendor != dev->id.vendor) continue; if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT) if (id->product != dev->id.product) continue; if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION) if (id->version != dev->id.version) continue; MATCH_BIT(evbit, EV_MAX); MATCH_BIT(,, KEY_MAX); MATCH_BIT(relbit, REL_MAX); MATCH_BIT(absbit, ABS_MAX); MATCH_BIT(mscbit, MSC_MAX); MATCH_BIT(ledbit, LED_MAX); MATCH_BIT(sndbit, SND_MAX); MATCH_BIT(ffbit, FF_MAX); MATCH_BIT(swbit, SW_MAX); return id; } return NULL;}MATCH_BIT宏的定义如下:#define MATCH_BIT(bit, max) for (i = 0; i  if ((id->bit & dev->bit) != id->bit) break; if (i != BITS_TO_LONGS(max)) continue;由 此看到。在id->flags中定义了要匹配的项。定义INPUT_DEVICE_ID_MATCH_BUS。则是要比较input device和input handler的总线类型。 INPUT_DEVICE_ID_MATCH_VENDOR,INPUT_DEVICE_ID_MATCH_PRODUCT,INPUT_DEVICE_ID_MATCH_VERSION 分别要求设备厂商。设备号和设备版本.如果id->flags定义的类型匹配成功。或者是id->flags没有定义,就会进入到 MATCH_BIT的匹配项了.从MATCH_BIT宏的定义可以看出。只有当iput device和input handler的id成员在evbit, keybit,… swbit项相同才会匹配成功。而且匹配的顺序是从evbit, keybit到swbit.只要有一项不同,就会循环到id中的下一项进行比较.简而言之,注册input device的过程就是为input device设置默认值,并将其挂以input_dev_list.与挂载在input_handler_list中的handler相匹配。如果匹配成功,就会调用handler的connect函数.四:handler注册分析Handler注册的接口如下所示:int input_register_handler(struct input_handler *handler){ struct input_dev *dev; int retval; retval = mutex_lock_interruptible(&input_mutex); if (retval) return retval; INIT_LIST_HEAD(&handler->h_list); if (handler->fops != NULL) { if (input_table[handler->minor >> 5]) { retval = -EBUSY; goto out; } input_table[handler->minor >> 5] = handler; } list_add_tail(&handler->node, &input_handler_list); list_for_each_entry(dev, &input_dev_list, node) input_attach_handler(dev, handler); input_wakeup_procfs_readers();out: mutex_unlock(&input_mutex); return retval;}handler->minor表示对应input设备节点的次设备号.以handler->minor右移五位做为索引值插入到input_table[ ]中..之后再来分析input_talbe[ ]的作用.然后将handler挂到input_handler_list中.然后将其与挂在input_dev_list中的input device匹配.这个过程和input device的注册有相似的地方.都是注册到各自的链表,.然后与另外一条链表的对象相匹配.

五:handle的注册int input_register_handle(struct input_handle *handle){
struct input_handler *handler = handle->handler; struct input_dev *dev = handle->dev; int error; /* * We take dev->mutex here to prevent race with * input_release_device(). */ error = mutex_lock_interruptible(&dev->mutex); if (error) return error; list_add_tail_rcu(&handle->d_node, &dev->h_list); mutex_unlock(&dev->mutex); synchronize_rcu();  list_add_tail(&handle->h_node, &handler->h_list); if (handler->start) handler->start(handle); return 0;}在这个函数里所做的处理其实很简单.将handle挂到所对应input device的h_list链表上.还将handle挂到对应的handler的hlist链表上.如果handler定义了start函数,将调用之.到这里,我们已经看到了input device, handler和handle是怎么关联起来的了.以图的方式总结如下:   

六:event事件的处理我们在开篇的时候曾以linux kernel文档中自带的代码作分析.提出了几个事件上报的API.这些API其实都是input_event()的封装.代码如下:void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value){ unsigned long flags; //判断设备是否支持这类事件 if (is_event_supported(type, dev->evbit, EV_MAX)) { spin_lock_irqsave(&dev->event_lock, flags); //利用键盘输入来调整随机数产生器 add_input_randomness(type, code, value); input_handle_event(dev, type, code, value); spin_unlock_irqrestore(&dev->event_lock, flags); }}首先,先判断设备产生的这个事件是否合法.如果合法,流程转入到input_handle_event()中.代码如下:static void input_handle_event(struct input_dev *dev, unsigned int type, unsigned int code, int value){ int disposition = INPUT_IGNORE_EVENT; switch (type) { case EV_SYN: switch (code) { case SYN_CONFIG: disposition = INPUT_PASS_TO_ALL; break; case SYN_REPORT: if (!dev->sync) { dev->sync = 1; disposition = INPUT_PASS_TO_HANDLERS; } break; } break; case EV_KEY: //判断按键值是否被支持 if (is_event_supported(code, dev->keybit, KEY_MAX) && !!test_bit(code, dev->key) != value) { if (value != 2) { __change_bit(code, dev->key); if (value) input_start_autorepeat(dev, code); } disposition = INPUT_PASS_TO_HANDLERS; } break; case EV_SW: if (is_event_supported(code, dev->swbit, SW_MAX) && !!test_bit(code, dev->sw) != value) { __change_bit(code, dev->sw); disposition = INPUT_PASS_TO_HANDLERS; } break;

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/98913/showart_2054759.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP