serio
总线也是
kernel
中的一种虚拟的串行输入输出总线,源码
/drivers/input/serio
目录下有很多与之相关的驱动程序。
一. serio
初始化
和之前分析 platform
总线一样,在系统启动时初始化时也创建了
serio_bus
总线:
static int __init
serio_init(void)
{
int
error;
error =
bus_register(&serio_bus);
if (error)
{
printk(KERN_ERR "serio: failed to
register serio bus, error: %d/n",
error);
return
error;
}
serio_task =
kthread_run(serio_thread, NULL,
"kseriod");
if (IS_ERR(serio_task))
{
bus_unregister(&serio_bus);
error =
PTR_ERR(serio_task);
printk(KERN_ERR "serio: Failed to
start kseriod, error: %d/n",
error);
return
error;
}
return
0;
}
serio_bus
定义如下:
static struct bus_type serio_bus
= {
.name
=
"serio",
.dev_attrs
=
serio_device_attrs,
.drv_attrs
=
serio_driver_attrs,
.match
=
serio_bus_match,
.uevent
=
serio_uevent,
.probe
=
serio_driver_probe,
.remove
=
serio_driver_remove,
.shutdown
=
serio_shutdown,
#ifdef
CONFIG_PM
.pm
=
&serio_pm_ops,
#endif
};
其中的各个函数将在使用到的地方再作分析。
初始化函数 serio_init()
首先注册了
serio_bus
总线,然后创建了一个内核线程
serio_thread
,这个内核线程做什么用的呢?之前分析
platform
总线并没有这个线程,这里为什么要用它?我们先看看
serio_thread
内核线程的内容:
static int serio_thread(void
*nothing)
{
set_freezable();
do
{
serio_handle_event();
wait_event_freezable(serio_wait,
kthread_should_stop() ||
!list_empty(&serio_event_list));
} while
(!kthread_should_stop());
printk(KERN_DEBUG "serio: kseriod
exiting/n");
return
0;
}
该线程首先执行 serio_handle_event()
函数,然后在
serio_wait
等待队列上休眠,如果
kthread_should_stop()
返回
0
的时候也即模块移除调用
kthread_stop(serio_task)
时,
serio_thread
线程返回。我们猜想:在某个时候往
serio_event_list
链表上添加成员时唤醒或等到下一时钟周期唤醒
serio_wait
工作队列,这时候就会去执行
serio_handle_event()
函数,这个函数将会对
serio_event_list
进行操作,为什么要把事件的处理放在内核线程中呢?因为在产生事件时是在关中断状态,同时需要同步,要获得锁,在后面的分析中我们会看到这个锁是
serio_event_lock
,而不能让事件长时间处在关中断状态并且占有着锁,所以延后了事件的处理,先释放该锁并恢复中断状态。在后面的代码分析中我们将看到这点。
serio_handle_event()
函数如下:
static void
serio_handle_event(void)
{
struct serio_event
*event;
mutex_lock(&serio_mutex);
if ((event = serio_get_event()))
{
switch (event->type)
{
case
SERIO_REGISTER_PORT:
serio_add_port(event->object);
break;
case
SERIO_RECONNECT_PORT:
serio_reconnect_port(event->object);
break;
case
SERIO_RESCAN_PORT:
serio_disconnect_port(event->object);
serio_find_driver(event->object);
break;
case
SERIO_RECONNECT_CHAIN:
serio_reconnect_chain(event->object);
break;
case
SERIO_ATTACH_DRIVER:
serio_attach_driver(event->object);
break;
default:
break;
}
serio_remove_duplicate_events(event);
serio_free_event(event);
}
mutex_unlock(&serio_mutex);
}
没错它就是在 serio_event_list
上获得事件,并将其在
serio_event_list
上删除,看下面这个函数:
static struct serio_event
*serio_get_event(void)
{
struct serio_event
*event;
struct list_head
*node;
unsigned long
flags;
spin_lock_irqsave(&serio_event_lock,
flags);
if
(list_empty(&serio_event_list))
{
spin_unlock_irqrestore(&serio_event_lock,
flags);
return
NULL;
}
node =
serio_event_list.next;
event = list_entry(node, struct
serio_event, node);
list_del_init(node);
spin_unlock_irqrestore(&serio_event_lock,
flags);
return
event;
}
获得事件后根据事件的类型作相应的事件处理,一共有五种事件,看下面定义:
enum serio_event_type
{
SERIO_RESCAN_PORT,
SERIO_RECONNECT_PORT,
SERIO_RECONNECT_CHAIN,
SERIO_REGISTER_PORT,
SERIO_ATTACH_DRIVER,
};
对于这些事件我们在用到时再作分析。
处理完事件后调用 serio_remove_duplicate_events(event)
删除链表上具有相同请求的事件,因为在事件被处理前有可能已经多次请求该事件。然后调用
serio_free_event(event)
减少相应的计数,释放其内存空间。
二. serio
设备的注册
先看看 serio
的数据结构:
struct serio
{
void
*port_data;
char
name[32];
char
phys[32];
bool
manual_bind;
bool registered;
struct serio_device_id
id;
spinlock_t lock;
int (*write)(struct serio *, unsigned
char);
int (*open)(struct serio
*);
void (*close)(struct serio
*);
int (*start)(struct serio
*);
void (*stop)(struct serio
*);
struct serio *parent,
*child;
unsigned int
depth;
struct serio_driver
*drv;
struct mutex
drv_mutex;
struct device
dev;
struct list_head
node;
};
该结构包含了 write
、
open
、
close
、
start
、
stop
函数,这些函数将会在事件处理中用到。
我们接着看 serio
设备的注册函数:
static inline void
serio_register_port(struct serio
*serio)
{
__serio_register_port(serio,
THIS_MODULE);
}
转入 __serio_register_port(serio,
THIS_MODULE) :
void __serio_register_port(struct
serio *serio, struct module *owner)
{
serio_init_port(serio);
serio_queue_event(serio, owner,
SERIO_REGISTER_PORT);
}
先调用 serio_init_port(serio)
进行初始化:
static void
serio_init_port(struct serio
*serio)
{
static atomic_t serio_no =
ATOMIC_INIT(0);
__module_get(THIS_MODULE);
INIT_LIST_HEAD(&serio->node);
spin_lock_init(&serio->lock);
mutex_init(&serio->drv_mutex);
device_initialize(&serio->dev);
dev_set_name(&serio->dev,
"serio%ld",
(long)atomic_inc_return(&serio_no) -
1);
serio->dev.bus =
&serio_bus;
serio->dev.release =
serio_release_port;
if (serio->parent)
{
serio->dev.parent =
&serio->parent->dev;
serio->depth =
serio->parent->depth +
1;
}
else
serio->depth =
0;
lockdep_set_subclass(&serio->lock,
serio->depth);
}
对 serio
的大部分字段初始化以及初始化其内嵌的
dev
,从对
depth
的初始化中可以看出它表示该设备是第几代孩子,如果是第
0
代,其
sysfs
将会在
sys/devices
下。
__serio_register_port()
函数接着调用
serio_queue_event(serio,
owner, SERIO_REGISTER_PORT)
看下这个函数:
static int serio_queue_event(void
*object, struct module *owner,
enum serio_event_type
event_type)
{
unsigned long
flags;
struct serio_event
*event;
int retval =
0;
spin_lock_irqsave(&serio_event_lock,
flags);
list_for_each_entry_reverse(event,
&serio_event_list, node)
{
if (event->object == object)
{
if (event->type ==
event_type)
goto
out;
break;
}
}
event = kmalloc(sizeof(struct
serio_event), GFP_ATOMIC);
if (!event)
{
printk(KERN_ERR
"serio: Not enough memory to queue
event %d/n",
event_type);
retval =
-ENOMEM;
goto
out;
}
if (!try_module_get(owner))
{
printk(KERN_WARNING
"serio: Can't get module reference,
dropping event %d/n",
event_type);
kfree(event);
retval =
-EINVAL;
goto
out;
}
event-> type =
event_type;
event->object =
object;
event->owner =
owner;
list_add_tail(&event->node,
& serio_event_list);
wake_up(&serio_wait);
out:
spin_unlock_irqrestore(&serio_event_lock,
flags);
return
retval;
}
从这个函数首先保存中断状态,关中断并获得
serio_event_lock
自旋锁,接着检查参数
object
代表的
event
是否在链表
serio_event_list
上已经存在,如果存在则退出,否则分配一个
serio_event
内存空间,并用输入参数初始化它的
type
、
object
和
owner
字段,并将其加到
serio_event_list
链表尾部,然后唤醒等待列表
serio_wait
,恢复中断和释放锁,这里我们看到,和前面的分析一致。
serio_event
结构体定义如下:
struct serio_event
{
enum serio_event_type
type;
void
*object;
struct module
*owner;
struct list_head
node;
};
对于 serio
设备的注册,在调用
serio_queue_event()
是事件的类型参数为
SERIO_REGISTER_PORT
,我们看看
serio_thread
内核线程中相应的处理:
.
.
switch (event->type)
{
case
SERIO_REGISTER_PORT:
serio_add_port(event->object);
break;
.
.
它将调用 serio_add_port(event->object)
,看一下这个函数:
static void serio_add_port(struct
serio *serio)
{
int
error;
if (serio ->parent)
{
serio_pause_rx(serio->parent);
serio->parent->child =
serio;
serio_continue_rx(serio->parent);
}
list_add_tail(&serio->node,
&serio_list);
if
(serio->start)
serio->start(serio);
error =
device_add(&serio->dev);
if
(error)
printk(KERN_ERR
"serio: device_add() failed for %s
(%s), error: %d/n",
serio->phys, serio->name,
error);
else
{
serio->registered =
true;
error =
sysfs_create_group(&serio->dev.kobj,
&serio_id_attr_group);
if
(error)
printk(KERN_ERR
"serio: sysfs_create_group() failed
for %s (%s), error: %d/n",
serio->phys, serio->name,
error);
}
}
如果 serio->
存在,则设置其父子关系,接着调用
list_add_tail(&serio->node,
&serio_list) 将 serio
插入到
serio_list
链表尾部,如果
serio->start
存在,则调用它,然后调用
device_add(&serio->dev)
将其注册到相应的总线上。
删除总线上已注册的 serio
设备要调用
serio_unregister_port
(),函数代码如下:
void serio_unregister_port(struct
serio *serio)
{
mutex_lock(&serio_mutex);
serio_disconnect_port(serio);
serio_destroy_port(serio);
mutex_unlock(&serio_mutex);
}
删除其后代子孙及他们的驱动
关联
,看下相应的函数:
static void
serio_disconnect_port(struct serio
*serio)
{
struct serio *s,
*parent;
if (serio->child)
{
for (s = serio; s->child; s =
s->child)
;
do
{
parent =
s->parent;
device_release_driver(&s->dev);
serio_destroy_port(s);
} while ((s = parent) !=
serio);
}
device_release_driver(&serio->dev);
}
找到最末代的子孙,然后一次往上代删除其驱动
关联
和设备,最后删除
serio
本身驱动
关联
和设备。
device_release_driver()
函数将删除它和
driver
以及
bus
的
关联
,请参考本站设备模型部分内容。
serio_destroy_port()
函数如下:
static void
serio_destroy_port(struct serio
*serio)
{
struct serio
*child;
child =
serio_get_pending_child(serio);
if (child)
{
serio_remove_pending_events(child);
put_device(&child->dev);
}
if
(serio->stop)
serio->stop(serio);
if (serio->parent)
{
serio_pause_rx(serio->parent);
serio->parent->child =
NULL;
serio_continue_rx(serio->parent);
serio->parent =
NULL;
}
if (serio->registered)
{
sysfs_remove_group(&serio->dev.kobj,
&serio_id_attr_group);
device_del(&serio->dev);
serio->registered =
false;
}
list_del_init(&serio->node);
serio_remove_pending_events(serio);
put_device(&serio->dev);
}
如果 serio_event_list
链表上存在未完成注册的该
serio
的孩子,则先删除它,看下面两个函数:
static struct serio
*serio_get_pending_child(struct serio
*parent)
{
struct serio_event
*event;
struct serio *serio, *child =
NULL;
unsigned long
flags;
spin_lock_irqsave(&serio_event_lock,
flags);
list_for_each_entry(event,
&serio_event_list, node)
{
if (event->type ==
SERIO_REGISTER_PORT) {
serio =
event->object;
if (serio->parent == parent)
{
child =
serio;
break;
}
}
}
spin_unlock_irqrestore(&serio_event_lock,
flags);
return
child;
}
static void
serio_remove_pending_events(void
*object)
{
struct list_head *node,
*next;
struct serio_event
*event;
unsigned long
flags;
spin_lock_irqsave(&serio_event_lock,
flags);
list_for_each_safe(node, next,
&serio_event_list) {
event = list_entry(node, struct
serio_event, node);
if (event->object == object)
{
list_del_init(node);
serio_free_event(event);
}
}
spin_unlock_irqrestore(&serio_event_lock,
flags);
}
这两个函数很容易就看懂,不再分析,接着继续
serio_destroy_port()
,如果
serio->stop
存在,则调用它,也即在设备删除时会调用它,痛上面的
start
函数,我们在编写具体的设备驱动时要编写这些对应的函数,还有另外三个函数
write
、
open
、
close
,还后面会分析到。
serio_destroy_port()
接着
serio
断开与它的父设备的关系,删除
group
调用
device_del()
删除内嵌的
device
,清
registered
标志,然后在链表
serio_list
上删除
serio->node
,删除
serio_event_list
链表上与它相关的所有事件请求,最后调用
put_device(&serio->dev)
减少其计数,如果计数为
0
则释放其内存空间。
serio_unregister_port()
分析完了。
接着看 serio_thread
内核线程中对另外四种类型事件的处理,首先看
SERIO_ATTACH_DRIVER
对应的操作:
case
SERIO_ATTACH_DRIVER:
serio_attach_driver(event->object);
break;
serio_attach_driver()
函数如下:
static void
serio_attach_driver(struct serio_driver
*drv)
{
int
error;
error =
driver_attach(&drv->driver);
if
(error)
printk(KERN_WARNING
"serio: driver_attach() failed for %s
with error %d/n",
drv->driver.name,
error);
}
进行一次设备驱动, driver_attach()
将扫面总线上所有的设备,如果和
drv->driver
匹配则将它们关联。
接着看 SERIO_RESCAN_PORT
对应的操作:
case
SERIO_RESCAN_PORT:
serio_disconnect_port(event->object);
serio_find_driver(event->object);
break;
serio_disconnect_port
函数在上面分析
serio_unregister_port()
已经分析,这里不再累赘。
serio_find_driver()
函数如下:
static void
serio_find_driver(struct serio
*serio)
{
int
error;
error =
device_attach(&serio->dev);
if (error <
0)
printk(KERN_WARNING
"serio: device_attach() failed for %s
(%s), error: %d/n",
serio->phys, serio->name,
error);
}
它调用 device_attach()
去匹配总线上的驱动,如果找到合适的驱动就将它们关联,这个函数在本站设备驱动模型的文章中已经详述。
接着看 SERIO_RECONNECT_PORT
对应的操作:
case
SERIO_RECONNECT_PORT:
serio_reconnect_port(event->object);
break;
serio_reconnect_port
() 函数如下:
static int
serio_reconnect_port(struct serio
*serio)
{
int error =
serio_reconnect_driver(serio);
if (error)
{
serio_disconnect_port(serio);
serio_find_driver(serio);
}
return
error;
}
断开 关联 重新匹配驱动。
接着看 SERIO_RECONNECT_CHAIN
对应的操作:
case
SERIO_RECONNECT_CHAIN:
serio_reconnect_chain(event->object);
break;
serio_reconnect_chain
() 函数如下:
static void
serio_reconnect_chain(struct serio
*serio)
{
do
{
if (serio_reconnect_port(serio))
{
break;
}
serio =
serio->child;
} while
(serio);
}
扩充了 SERIO_RECONNECT_PORT
事件,如果
serio
的子孙后代存在,则对它们做相同的操作。
至此,所有的事件处理都分析完了。