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目录中为驱动创建目录。 同时查找该驱动匹配的设备。(这一点暂不太明白)
阅读(2381) | 评论(0) | 转发(1) |