原文地址:http://blog.chinaunix.net/uid-24631445-id-3428100.html
1:device_driver结构体
-
struct device_driver {
-
const char *name;
-
struct bus_type *bus;
-
-
struct module *owner;
-
const char *mod_name; /* used for built-in modules */
-
-
bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
-
-
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 {
-
struct kobject kobj;
-
struct klist klist_devices;
-
struct klist_node knode_bus;
-
struct module_kobject *mkobj;
-
struct device_driver *driver;
-
};
-
-
-
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);
-
};
-
-
/* 一个attribute_group中包含一组attribute。用sysfs_create_group,可以为这一组属性创建文件,文件都处于表示该group的name目录中。*/
-
-
struct attribute_group {
-
const char *name;
-
mode_t (*is_visible)(struct kobject *,
-
struct attribute *, int);
-
struct attribute **attrs;
-
};
从device_driver结构体可知,一个驱动中会有一组attribute_group,因此驱动的属性文件可能在多个子目录中。
2:创建属性文件的函数
-
int driver_create_file(struct device_driver *drv,
-
struct driver_attribute *attr)
-
{
-
int error;
-
if (drv)
-
error = sysfs_create_file(&drv->p->kobj, &attr->attr);
-
else
-
error = -EINVAL;
-
return error;
-
}
-
-
void driver_remove_file(struct device_driver *drv,
-
struct driver_attribute *attr)
-
{
-
if (drv)
-
sysfs_remove_file(&drv->p->kobj, &attr->attr);
-
}
3:驱动注册
正如总线有bus_register, 设备有device_register, 驱动有driver_register。都是重要函数呀。
-
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);
-
/* 在drv->bus的driver_kset中查找名字为drv->name的驱动是否已经存在,
-
不存在就返回NULL */
-
other = driver_find(drv->name, drv->bus);
-
if (other) {
-
/* 若已存在则用put_driver增加驱动的kobj的引用计数 */
-
put_driver(other);
-
printk(KERN_ERR "Error: Driver '%s' is already registered, "
-
"aborting...\n", drv->name);
-
return -EBUSY;
-
}
-
/* 若没找到,则对该bus添加该驱动。(见下面) */
-
ret = bus_add_driver(drv);
-
if (ret)
-
return ret;
-
/* 为driver的所有属性group在sysfs中创建文件夹和文件 */
-
ret = driver_add_groups(drv, drv->groups);
-
if (ret)
-
bus_remove_driver(drv);
-
return ret;
-
}
-
-
-
-
int bus_add_driver(struct device_driver *drv)
-
{
-
struct bus_type *bus;
-
struct driver_private *priv;
-
int error = 0;
-
/* 获得驱动的总线,可见注册驱动前必须先设定好驱动的总线 */
-
bus = bus_get(drv->bus);
-
if (!bus)
-
return -EINVAL;
-
-
pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);
-
/* 为驱动的私有数据分配空间,bus_type和device都存在私有数据 */
-
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-
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; // 在调用bus_register创建的drivers目录
-
/* kobject的初始化和注册,这样便在drivers目录下为该驱动创建了一个目录 */
-
error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
-
"%s", drv->name);
-
if (error)
-
goto out_unregister;
-
-
if (drv->bus->p->drivers_autoprobe) {
-
/* 这里大致的意思是,将driver与device匹配起来,这个函数涉及到了bus, device, driver,
-
需要结合例子来讲,下次遇到个真实的driver后,再来说这个,目前还不太懂。
-
既然涉及了bus,device,driver, 也许从这里来理解这三者的关系会比较好 */
-
error = driver_attach(drv);
-
if (error)
-
goto out_unregister;
-
}
-
/* 看来关于klist和klist_node得另外写文章来说了,还有module结构体,一直不知道作用是什么 */
-
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
-
module_add_driver(drv->owner, drv);
-
-
/* 为属性创建文件 */
-
error = driver_create_file(drv, &driver_attr_uevent);
-
if (error) {
-
printk(KERN_ERR "%s: uevent attr (%s) failed\n",
-
__func__, drv->name);
-
}
-
/* 在bus结构中有一个drv_attrs指针,如果总线类型设定了该值,则为其执行的一组属性创建文件。
-
并不是一定会有,比如pci_bus_type中没有设定drv_attrs的值 */
-
error = driver_add_attrs(bus, drv);
-
if (error) {
-
/* How the hell do we get out of this pickle? Give up */
-
printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
-
__func__, drv->name);
-
}
-
-
if (!drv->suppress_bind_attrs) {
-
/* 为driver_attr_unbind属性和driver_attr_bind属性创建文件 */
-
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);
-
return 0;
-
-
out_unregister:
-
kfree(drv->p);
-
drv->p = NULL;
-
kobject_put(&priv->kobj);
-
out_put_bus:
-
bus_put(bus);
-
return error;
-
}
-
在驱动注册的过程中,会在/sys/bus下相应的总线目录中的driver目录中为驱动创建目录。 同时查找该驱动匹配的设备。(这一点暂不太明白)
阅读(1479) | 评论(0) | 转发(0) |