输入核心层,是input子系统实现的核心。
对下(设备驱动层),提供设备注册接口,输入信息反馈接口。
对上(事件驱动层),提供事件注册接口,等。
一.先学习input子系统自己的实现。
注册input子系统本身很简单只需要在sysfs中注册号相应的设备类和主设备号即可。
下面有难度的是初始化input子系统的proc文件系统,但这不是我们这次分析的核心,也不是必须的,所以proc文件系统相关的我们就先不分析来。
static char *input_devnode(struct device *dev, mode_t *mode)
{
return kasprintf(GFP_KERNEL, "input/%s", dev_name(dev));
}
struct class input_class = {
.name = "input",
.devnode = input_devnode,
};
static int __init input_init(void)
{
int err;
input_init_abs_bypass(); /* 触摸屏类设备比较特殊,要先初始化一些数据 */
err = class_register(&input_class); /* 在sysfs中的class类下注册一个input的类 */
if (err) {
printk(KERN_ERR "input: unable to register input_dev class\n");
return err;
}
err = input_proc_init(); /* 初始化proc文件系统 */
if (err)
goto fail1;
err = register_chrdev(INPUT_MAJOR, "input", &input_fops); /* 注册字符设备驱动 */
if (err) {
printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
goto fail2;
}
return 0;
fail2: input_proc_exit();
fail1: class_unregister(&input_class);
return err;
}
取消注册就更简单来,和注册相反即可。
static void __exit input_exit(void)
{
input_proc_exit(); /* 卸载input的proc文件系统内的信息 */
unregister_chrdev(INPUT_MAJOR, "input"); /* 注销该字符设备驱动 */
class_unregister(&input_class); /* 注销类 */
}
二.设备驱动层提供的接口函数学习。
1.设备描述结构体变量,同时初始化一些通用性数据。(不同设备特有的数据需要自己填充)
/**
* input_allocate_device - allocate memory for new input device
*
* Returns prepared struct input_dev or NULL.
*
* NOTE: Use input_free_device() to free devices that have not been
* registered; input_unregister_device() should be used for already
* registered devices.
*/
struct input_dev *input_allocate_device(void)
{
struct input_dev *dev;
dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL); /* 申请内存 */
if (dev) {
dev->dev.type = &input_dev_type; /* 绑定设备信息 */
dev->dev.class = &input_class; /* 绑定在sysfs所属的类,后面的register里面的add_device后才能出现在sysfs下的input文件夹下 */
device_initialize(&dev->dev); /* 设备初始化 */
mutex_init(&dev->mutex);
spin_lock_init(&dev->event_lock);
INIT_LIST_HEAD(&dev->h_list); /* 初始化链表 */
INIT_LIST_HEAD(&dev->node);
__module_get(THIS_MODULE);
}
return dev;
}
2.设置dev设备的能力,只有注册前设置来它拥有的能力,将来该设备注册后,发送的信息才能被上报。
注意:该函数每次只能设置一个能力。
/* 根据type类型,设置code到相应的typebit */
/**
* input_set_capability - mark device as capable of a certain event
* @dev: device that is capable of emitting or accepting event
* @type: type of the event (EV_KEY, EV_REL, etc...)
* @code: event code
*
* In addition to setting up corresponding bit in appropriate capability
* bitmap the function also adjusts dev->evbit.
*/
void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code)
{
switch (type) {
case EV_KEY:
__set_bit(code, dev->keybit);
break;
case EV_REL:
__set_bit(code, dev->relbit);
break;
case EV_ABS:
__set_bit(code, dev->absbit);
break;
case EV_MSC:
__set_bit(code, dev->mscbit);
break;
case EV_SW:
__set_bit(code, dev->swbit);
break;
case EV_LED:
__set_bit(code, dev->ledbit);
break;
case EV_SND:
__set_bit(code, dev->sndbit);
break;
case EV_FF:
__set_bit(code, dev->ffbit);
break;
case EV_PWR:
/* do nothing */
break;
default:
printk(KERN_ERR
"input_set_capability: unknown type %u (code %u)\n",
type, code);
dump_stack();
return;
}
__set_bit(type, dev->evbit);
}
3.具体设备注册(需要前两步申请空间和填充能力后才能注册)
/**
* input_register_device - register device with input core
* @dev: device to be registered
*
* This function registers device with input core. The device must be
* allocated with input_allocate_device() and all it's capabilities
* set up before registering.
* If function fails the device must be freed with input_free_device().
* Once device has been successfully registered it can be unregistered
* with input_unregister_device(); input_free_device() should not be
* called in this case.
*/
int input_register_device(struct input_dev *dev)
{
static atomic_t input_no = ATOMIC_INIT(0);
struct input_handler *handler;
const char *path;
int error;
/* Every input device generates EV_SYN/SYN_REPORT events. */
__set_bit(EV_SYN, dev->evbit); /* 通用的同步包 */
/* KEY_RESERVED is not supposed to be transmitted to userspace. */
__clear_bit(KEY_RESERVED, dev->keybit);
/* Make sure that bitmasks not mentioned in dev->evbit are clean. */
input_cleanse_bitmasks(dev);
/*
* If delay and period are pre-set by the driver, then autorepeating
* is handled by the driver itself and we don't do it in input.c.
*/
init_timer(&dev->timer); /* 重复上报功能数据填充 */
if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
dev->timer.data = (long) dev;
dev->timer.function = input_repeat_key;
dev->rep[REP_DELAY] = 250;
dev->rep[REP_PERIOD] = 33;
}
/* 下面继续填充结构体 */
if (!dev->getkeycode)
dev->getkeycode = input_default_getkeycode;
if (!dev->setkeycode)
dev->setkeycode = input_default_setkeycode;
/* 设置设备名字,从input0开始,依次增大1 */
dev_set_name(&dev->dev, "input%ld",
(unsigned long) atomic_inc_return(&input_no) - 1);
/* 把该inputx设备加入到设备链表中,同时在sysfs的input文件夹系出现inputx以及我们初始化的name,phy等参数 */
error = device_add(&dev->dev);
if (error)
return error;
/* 打印调试信息,安装设备会出现 */
path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
printk(KERN_INFO "input: %s as %s\n",
dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
kfree(path);
error = mutex_lock_interruptible(&input_mutex);
if (error) {
device_del(&dev->dev);
return error;
}
/* 把该设备加入到核心层维护的两个重要链表之一的设备链表中去 */
list_add_tail(&dev->node, &input_dev_list);
/* 依次遍历另一条重要链表input_handler_list,看该设备能不能匹配到那个handler */
list_for_each_entry(handler, &input_handler_list, node)
input_attach_handler(dev, handler); /*匹配,和链接两者 */
input_wakeup_procfs_readers(); /* 匹配到了,则更新peoc文件系统 */
mutex_unlock(&input_mutex);
return 0;
}
4.handler和dev做匹配,如果匹配上,则把两者绑定。
static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
{
const struct input_device_id *id;
int error;
id = input_match_device(handler, dev); /* 匹配handler和dev */
if (!id)
return -ENODEV;
error = handler->connect(handler, dev, id); /* 做具体的绑定handler和dev工作,由具体的事驱动层实现 */
if (error && error != -ENODEV)
printk(KERN_ERR
"input: failed to attach handler %s to device %s, "
"error: %d\n",
handler->name, kobject_name(&dev->dev.kobj), error);
return error;
}
5.匹配handler和dev
每一个事件驱动层在实现的时候都要实现一个struct input_device_id的表(数组),用来表明该事件驱动可以支持的设备。
struct input_device_id {
kernel_ulong_t flags; /* flags表明下面的四个要不要匹配,已经用相关宏定义好 */
__u16 bustype;
__u16 vendor;
__u16 product;
__u16 version;
kernel_ulong_t evbit[INPUT_DEVICE_ID_EV_MAX / BITS_PER_LONG + 1];
kernel_ulong_t keybit[INPUT_DEVICE_ID_KEY_MAX / BITS_PER_LONG + 1];
kernel_ulong_t relbit[INPUT_DEVICE_ID_REL_MAX / BITS_PER_LONG + 1];
kernel_ulong_t absbit[INPUT_DEVICE_ID_ABS_MAX / BITS_PER_LONG + 1];
kernel_ulong_t mscbit[INPUT_DEVICE_ID_MSC_MAX / BITS_PER_LONG + 1];
kernel_ulong_t ledbit[INPUT_DEVICE_ID_LED_MAX / BITS_PER_LONG + 1];
kernel_ulong_t sndbit[INPUT_DEVICE_ID_SND_MAX / BITS_PER_LONG + 1];
kernel_ulong_t ffbit[INPUT_DEVICE_ID_FF_MAX / BITS_PER_LONG + 1];
kernel_ulong_t swbit[INPUT_DEVICE_ID_SW_MAX / BITS_PER_LONG + 1];
kernel_ulong_t driver_info;
};
如果填充时在handler里面的在flags标志里面置位了下面的某一个,则匹配时就会检查响应的(总线类型,厂商,设备号,设备版本)。如果没有置位相应位,则表明匹配时不检查响应的标志位。
#define INPUT_DEVICE_ID_MATCH_BUS 1
#define INPUT_DEVICE_ID_MATCH_VENDOR 2
#define INPUT_DEVICE_ID_MATCH_PRODUCT 4
#define INPUT_DEVICE_ID_MATCH_VERSION 8
同时也可以置位需要匹配类型,
#define INPUT_DEVICE_ID_MATCH_EVBIT 0x0010
#define INPUT_DEVICE_ID_MATCH_KEYBIT 0x0020
#define INPUT_DEVICE_ID_MATCH_RELBIT 0x0040
#define INPUT_DEVICE_ID_MATCH_ABSBIT 0x0080
#define INPUT_DEVICE_ID_MATCH_MSCIT 0x0100
#define INPUT_DEVICE_ID_MATCH_LEDBIT 0x0200
#define INPUT_DEVICE_ID_MATCH_SNDBIT 0x0400
#define INPUT_DEVICE_ID_MATCH_FFBIT 0x0800
#define INPUT_DEVICE_ID_MATCH_SWBIT 0x1000
下面就是真正的通过input_device_id来匹配
static const struct input_device_id *input_match_device(struct input_handler *handler,
struct input_dev *dev)
{
const struct input_device_id *id;
int i;
/* input_device_id是一个数组,从前向后依次遍历id_table中和dev里面的id和xxbit中完全匹配的 */
for (id = handler->id_table; id->flags || id->driver_info; id++) {
if (id->flags & INPUT_DEVICE_ID_MATCH_BUS) /* 正如前面描述的handler中id_table置位了相应标志位才做匹配检查 */
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;
/* 同一id_table里面的flags匹配成功,才能MATCH_BIT匹配 */
MATCH_BIT(evbit, EV_MAX);
MATCH_BIT(keybit, 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);
/* 看handler层有没有再定义macth匹配函数,如果没有,那到这里就是已经找到id了,否则,还要通过handler里面的match才能确定就是该id */
if (!handler->match || handler->match(handler, dev))
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;
假设以keybit为例,宏替换后如下。可以发现,就是匹配handler里面的keybit值的dev里面keybit值。即每一项都要满足id_table中,该项(keybit的值)。即dev的key值可以有 1 2 3 4 5 6,handler中id_table可以只有1,2,3。这样也能匹配成功。
for (i = 0; i < BITS_TO_LONGS(KEY_MAX); i++)
if ((id->keybit[i] & dev->keybit[i]) != id->keybit[i])
break;
if (i != BITS_TO_LONGS(KEY_MAX))
continue;
下面我们以evdev的id_table分别举例,方便上面的理解。
首先看evdev的id_table:可以发现,它里面除了driver_info其他都是空的。即evdev的handler可以匹配所有的device
即空的flags:不用匹配flags
空的xxbit,不用匹配xxbit
static const struct input_device_id evdev_ids[] = {
{ .driver_info = 1 }, /* Matches all devices */
{ }, /* Terminating zero entry */
};
6.input_register_device分析完毕,那就剩下一个unregister了。
它和register的顺序刚好相反,就不详细分析了。
/**
* input_unregister_device - unregister previously registered device
* @dev: device to be unregistered
*
* This function unregisters an input device. Once device is unregistered
* the caller should not try to access it as it may get freed at any moment.
*/
void input_unregister_device(struct input_dev *dev)
{
struct input_handle *handle, *next;
input_disconnect_device(dev);
mutex_lock(&input_mutex);
list_for_each_entry_safe(handle, next, &dev->h_list, d_node)
handle->handler->disconnect(handle);
WARN_ON(!list_empty(&dev->h_list));
del_timer_sync(&dev->timer);
list_del_init(&dev->node);
input_wakeup_procfs_readers();
mutex_unlock(&input_mutex);
device_unregister(&dev->dev);
}
至此,和核心层中input子系统和device相关的已经分析完毕。
三.事件驱动层提供的接口函数学习
接下来我们分析handler部分
1.首先肯定还是handler的注册了
/**
* input_register_handler - register a new input handler
* @handler: handler to be registered
*
* This function registers a new input handler (interface) for input
* devices in the system and attaches it to all input devices that
* are compatible with the 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]) { /* 每种handler的minor以32的倍数为base ,这里是检查当前handler类是不是已经注册过了,比如evdev的base是64,那么他就在input_table[2]中*/
retval = -EBUSY;
goto out;
}
input_table[handler->minor >> 5] = handler; /* 上面检查没被注册过,测在这里注册进input_table中 */
}
list_add_tail(&handler->node, &input_handler_list); /* 把当前handler加入到input核心增维护的两条重要链表之一的handler链表中去 */
/* 用当前的handler遍历核心层维护的两条重要链表之一的dev链表,并尝试匹配 */
list_for_each_entry(dev, &input_dev_list, node)
input_attach_handler(dev, handler);
input_wakeup_procfs_readers(); /* 更新proce文件系统 */
out:
mutex_unlock(&input_mutex);
return retval;
}
匹配算法和device那边的完全一样(调用的同一个函数都)。
这里要说明的是为什么即在注册handler的时候匹配一遍,又要在注册device的时候匹配一次。
这是因为,通常系统不能确定是handler先注册,还是dev先注册。
假设只在注册dev的时候匹配handler(注册handler去掉匹配那几句代码 ),结果,devi先执行的,因为handler还没被注册,所以dev匹配失败。当注册handler的时候,因为没有了再次匹配,所以两者无法再接续到一块了。所以要在handler和dev注册都匹配一次,当然肯定是后面注册的才能匹配成。
2.还有一个就是卸载handler函数了,这个我们就不分析了和注册方向相反分析即可。
/**
* input_unregister_handler - unregisters an input handler
* @handler: handler to be unregistered
*
* This function disconnects a handler from its input devices and
* removes it from lists of known handlers.
*/
void input_unregister_handler(struct input_handler *handler)
{
struct input_handle *handle, *next;
mutex_lock(&input_mutex);
list_for_each_entry_safe(handle, next, &handler->h_list, h_node)
handler->disconnect(handle);
WARN_ON(!list_empty(&handler->h_list));
list_del_init(&handler->node);
if (handler->fops != NULL)
input_table[handler->minor >> 5] = NULL;
input_wakeup_procfs_readers();
mutex_unlock(&input_mutex);
}
3.还有一个注册函数就是handle的注册(与其说注册,其实就是把handler和dev的链表加入到handle的数据中)
/**
* input_register_handle - register a new input handle
* @handle: handle to register
*
* This function puts a new input handle onto device's
* and handler's lists so that events can flow through
* it once it is opened using input_open_device().
*
* This function is supposed to be called from handler's
* connect() method.
*/
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;
/*
* Filters go to the head of the list, normal handlers
* to the tail.
*/
if (handler->filter)
list_add_rcu(&handle->d_node, &dev->h_list);
else
list_add_tail_rcu(&handle->d_node, &dev->h_list); /* 把dev加入到handle */
mutex_unlock(&dev->mutex);
/*
* Since we are supposed to be called from ->connect()
* which is mutually exclusive with ->disconnect()
* we can't be racing with input_unregister_handle()
* and so separate lock is not needed here.
*/
list_add_tail_rcu(&handle->h_node, &handler->h_list); /* 把handler加入到handle */
if (handler->start)
handler->start(handle);
return 0;
}
4.既然有handle的注册,那当然有handle的卸载了。
/**
* input_unregister_handle - unregister an input handle
* @handle: handle to unregister
*
* This function removes input handle from device's
* and handler's lists.
*
* This function is supposed to be called from handler's
* disconnect() method.
*/
void input_unregister_handle(struct input_handle *handle)
{
struct input_dev *dev = handle->dev;
list_del_rcu(&handle->h_node);
/*
* Take dev->mutex to prevent race with input_release_device().
*/
mutex_lock(&dev->mutex);
list_del_rcu(&handle->d_node);
mutex_unlock(&dev->mutex);
synchronize_rcu();
}
RCU形式的锁机制,它允许多个执行单元对它同时对它进行读,但是多个执行单元对它进行写操作时,并不会让你随随便便就碰她,它会要求你先复制一个副本,要改要删随你便,反正你改的不是她本身。当所有的写单元都一一改完后,再统一写回,是不是比一般的自旋锁高级多了。不过不要轻易用它,系统开销较大。