Chinaunix首页 | 论坛 | 博客
  • 博客访问: 401851
  • 博文数量: 107
  • 博客积分: 2536
  • 博客等级: 少校
  • 技术积分: 783
  • 用 户 组: 普通用户
  • 注册时间: 2009-06-14 15:19
文章分类

全部博文(107)

文章存档

2017年(11)

2016年(8)

2015年(14)

2014年(32)

2012年(1)

2011年(1)

2010年(7)

2009年(33)

我的朋友

分类: LINUX

2009-09-17 18:11:22

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 < BITS_TO_LONGS(max); i++)
 if ((id->bit[i] & dev->bit[i]) != id->bit[i])
 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;
阅读(1167) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~