您的位置:首页 > 其它

总线设备驱动模型——驱动篇

2015-08-18 20:14 281 查看

驱动struct device_driver

struct device_driver
{

const
char *name;
//驱动的名字
struct bus_type
*bus;
//驱动呈现属于的总线类型

struct module
*owner;
const
char *mod_name; /* usedfor built-in modules */

bool suppress_bind_attrs;
/* disables bind/unbind via sysfs */

const
struct of_device_id *of_match_table;

int (*probe)
(
struct device
*dev); //驱动挂载的时候调用
int (*remove)
(
struct device
*dev); //卸载的时候调用
void (*shutdown)
(
struct device
*dev);
int (*suspend)
(
struct device
*dev, pm_message_t state);
int (*resume)
(
struct device
*dev);
const
struct attribute_group **groups;

const
struct dev_pm_ops *pm;

struct driver_private
*p;
};

struct driver_private

与device类型相似,其中有一个指向driver_private的指针p,一些与其他的组件相关的联系都被移到这个结构变量中。由driver_private可以看出driver指针最后也由driver_private回到了device_driver之中。

struct driver_private
{

struct kobject kobj;
//在sysfs中代表目录本身
struct klist klist_devices;
//驱动链表
struct klist_node knode_bus;
//挂载在总线的驱动链表的节点
struct module_kobject
*mkobj;
//driver与相关的module之间的联系
struct device_driver
*driver;
};
#define to_driver(obj) container_of(obj,struct driver_private, kobj)

驱动属性struct driver_attribute

下面来看看驱动的属性文件的表示方法,这里只是有两个读写函数。

struct driver_attribute
{
struct attribute attr;
ssize_t (*show)(struct device_driver
*driver,
char *buf);
ssize_t (*store)(struct device_driver
*driver,
const
char *buf,
size_t count);
};

#define DRIVER_ATTR(_name, _mode, _show, _store) \
struct driver_attribute driver_attr_##_name = \
__ATTR(_name, _mode, _show, _store)

驱动注册driver_register()

看完了关于驱动的一些重要的数据结构,那么如何向内核注册一个drv呢?使用driver_register,首先drv->bus一定要预先设置,再使用driver_find从bus的驱动链表中特定名字的driver,然后就进入这个函数的重点bus_add_driver,几乎注册所有的工作都是由它来完成。

int driver_register(struct device_driver
*drv)
{
int ret;
struct device_driver
*other;

BUG_ON(!drv->bus->p);

if
((
drv->bus->probe
&& drv->probe)
||

(drv->bus->remove
&& drv->remove)
||

(drv->bus->shutdown
&& drv->shutdown))
printk(KERN_WARNING
"Driver '%s'needs updating - please use "
"bus_type methods\n", drv->name);

other = driver_find(drv->name, drv->bus);
if
(
other)
{

put_driver(other);
printk(KERN_ERR
"Error: Driver'%s' is already registered, "
"aborting...\n", drv->name);
return
-
EBUSY;
}

ret = bus_add_driver(drv);
if
(
ret)
return ret;
ret = driver_add_groups(drv, drv->groups);
if
(
ret)
bus_remove_driver(drv);
return ret;
}

几乎注册所有的工作都是由bus_add_driver来完成。

int bus_add_driver(struct device_driver
*drv)
{
struct bus_type
*
bus;
struct driver_private
*priv;
int error =
0;

bus = bus_get(drv->bus);
//增加对bus的引用
if
(!
bus)
return
-
EINVAL;

pr_debug("bus: '%s': adddriver %s\n", bus->name,
drv->name);

priv = kzalloc(sizeof(*priv),
GFP_KERNEL);//分配初始化一个drv->p,也就是上面的driver_private结构
if
(!
priv)
{

error =
-
ENOMEM;
goto out_put_bus;
}
klist_init(&priv->klist_devices,
NULL,
NULL);

priv->driver
= drv;
drv->p
=
priv;
priv->kobj.kset
= bus->p->drivers_kset;
error =kobject_init_and_add(&priv->kobj,
&
driver_ktype,
NULL,

"%s", drv->name);
//将drv加入sysfs
if
(
error)
goto out_unregister;

if
(
drv->bus->p->drivers_autoprobe)
{

error = driver_attach(drv);
//如果总线可以自动probe,就会调用匹配函数
if
(
error)
goto out_unregister;
}
klist_add_tail(&priv->knode_bus,
&
bus->p->klist_drivers);//将drv挂入到总线的链表中
module_add_driver(drv->owner, drv);
//创建driver相关的模块

error = driver_create_file(drv,
&
driver_attr_uevent);//在drv目录下创建event属性文件
if
(
error)
{

printk(KERN_ERR
"%s: ueventattr (%s) failed\n",
__func__, drv->name);
}
error = driver_add_attrs(bus, drv);
//添加属性
if
(
error)
{

/* How the hell do we get out of thispickle? Give up */
printk(KERN_ERR
"%s:driver_add_attrs(%s) failed\n",
__func__, drv->name);
}

if
(!
drv->suppress_bind_attrs)
{

error = add_bind_files(drv);
if
(
error)
{

/* Ditto */
printk(KERN_ERR
"%s:add_bind_files(%s) failed\n",
__func__, drv->name);
}
}

kobject_uevent(&priv->kobj, KOBJ_ADD);//向用户空间发布kobj_add消息
return
0;

out_unregister:
kobject_put(&priv->kobj);
kfree(drv->p);
drv->p
= NULL;

out_put_bus:
bus_put(bus);
return error;
}

其实上面的处理过程相对于设备来说简单很多,下面主要对当驱动挂接的时候,怎么去匹配进行分析。

int driver_attach(struct device_driver
*drv)
{
return bus_for_each_dev(drv->bus,
NULL,
drv, __driver_attach);
}

static
int __driver_attach(struct device
*dev,
void *data)
{
struct device_driver
*drv = data;

/*
* Lock device and try to bindto it. We drop the error
* here and always return 0,because we need to keep trying
* to bind to devices and somedrivers will return an error
* simply if it didn't supportthe device.
*
* driver_probe_device() willspit a warning if there
* is an error.
*/

if
(!
driver_match_device(drv, dev))
return
0;

if
(
dev->parent)
/* Needed for USB */
device_lock(dev->parent);
device_lock(dev);
if
(!
dev->driver)
driver_probe_device(drv, dev);
device_unlock(dev);
if
(
dev->parent)
device_unlock(dev->parent);

return
0;

}

最终也是调用总线的match函数来完成设备与驱动的匹配的过程。

static
inline int driver_match_device(struct device_driver
*drv,
struct device
*dev)
{
return drv->bus->match
? drv->bus->match(dev,
drv) :
1;
}

module_init(my_driver_init)

extern
struct bus_type my_bus_type;

static
int my_probe(struct device
*dev)
{
printk("Driver founddevice which my driver can handle!\n");
return
0;
}

static
int my_remove(struct device
*dev)
{
printk("Driver founddevice unpluged!\n");
return
0;
}

struct device_drivermy_driver
= {
.name
=
"my_dev",
.bus
= &
my_bus_type,
.probe
=
my_probe,
.remove
= my_remove,
};

/*
* Export a simple attribute.
*/
static ssize_tmydriver_show(struct device_driver
*driver,
char *buf)
{
return sprintf(buf,
"%s\n",
"This is mydriver!");
}

static DRIVER_ATTR(drv, S_IRUGO, mydriver_show,
NULL);


static
int __initmy_driver_init(void)
{
int ret =
0;

/*注册驱动*/
driver_register(&my_driver);

/*创建属性文件*/
driver_create_file(&my_driver,
&
driver_attr_drv);

return ret;

}

static
void my_driver_exit(void)
{
driver_unregister(&my_driver);
}

module_init(my_driver_init);
module_exit(my_driver_exit);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: