三,驱动
device_driver结构体的定义include/linux/Device.h
- 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;
- };
driver_register函数在driver/base/Driver.c中,此函数注册driver到相应总线。
- /**
- * driver_register - register driver with bus
- * @drv: driver to register
- *
- * We pass off most of the work to the bus_add_driver() call,
- * since most of the things we have to do deal with the bus
- * structures.
- */
- 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); //(1)
- 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); //(2)
- if (ret)
- return ret;
- ret = driver_add_groups(drv, drv->groups);
- if (ret)
- bus_remove_driver(drv);
- return ret;
- }
(1)在对应的总线上,通过驱动的名字查找驱动。如果查找到就说明已经注册过了。函数定义如下。
- struct device_driver *driver_find(const char *name, struct bus_type *bus)
- { //kset_find_obj在相应的set上查找kobject。函数分析在关于kobject的博文中有分析
- struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);
- struct driver_private *priv;
- if (k) {
- priv = to_driver(k);
- return priv->driver;
- }
- return NULL;
- }
(2)bus_add_driver函数向驱动关联的总线添加这个驱动,会生成目录和连接文件等
分析bus_add_driver函数,这个函数在drivers/base/Bus.c
- 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': add driver %s\n", bus->name, drv->name);
- priv = kzalloc(sizeof(*priv), GFP_KERNEL); //获取driver_private的空间(1)
- if (!priv) {
- error = -ENOMEM;
- goto out_put_bus;
- }
- klist_init(&priv->klist_devices, NULL, NULL);
- priv->driver = drv; //driver_private中的驱动指向drv
- drv->p = priv; //drv的私有结构(driver_private)指向这个私有结构priv
- priv->kobj.kset = bus->p->drivers_kset;
- //driver的kobject的kset 和 bus的kobject的kset 是相同的
- error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
- "%s", drv->name); //将这个driver的kobject注册进sysfs系统
- if (error)
- goto out_unregister;
- if (drv->bus->p->drivers_autoprobe) {
- error = driver_attach(drv); //将寻找这个总线上匹配相应的设备(2)
- if (error)
- goto out_unregister;
- }
- klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers); //将driver添加到bus的list列表中
- module_add_driver(drv->owner, drv); //添加到module(?)
- error = driver_create_file(drv, &driver_attr_uevent);//在驱动目录下添加uevent文件
- if (error) {
- printk(KERN_ERR "%s: uevent attr (%s) failed\n",
- __func__, drv->name);
- }
- error = driver_add_attrs(bus, drv); //将bus的属性都在driver目录下生成相应的属性文件
- 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) {
- error = add_bind_files(drv); //生成bind和unbind文件,可以手动实现driver和device的之间的匹配和移除
- if (error) {
- /* Ditto */
- printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
- __func__, drv->name);
- }
- }
- kobject_uevent(&priv->kobj, KOBJ_ADD);//通知用户空间uevent
- return 0;
- out_unregister:
- kfree(drv->p);
- drv->p = NULL;
- kobject_put(&priv->kobj);
- out_put_bus:
- bus_put(bus);
- return error;
- }
(1)driver_private定义
- struct driver_private {
- struct kobject kobj; //driver的kobject结构体
- struct klist klist_devices; //
- struct klist_node knode_bus;
- struct module_kobject *mkobj;
- struct device_driver *driver; //一般再指向包含自身的驱动
- };
(2)寻找总线上此驱动对应的设备
- int driver_attach(struct device_driver *drv)
- {
- return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
- }
- /**
- * bus_for_each_dev - device iterator.
- * @bus: bus type.
- * @start: device to start iterating from.
- * @data: data for the callback.
- * @fn: function to be called for each device.
- *
- * Iterate over @bus's list of devices, and call @fn for each,
- * passing it @data. If @start is not NULL, we use that device to
- * begin iterating from.
- *
- * We check the return of @fn each time. If it returns anything
- * other than 0, we break out and return that value.
- *
- * NOTE: The device that returns a non-zero value is not retained
- * in any way, nor is its refcount incremented. If the caller needs
- * to retain this data, it should do so, and increment the reference
- * count in the supplied callback.
- */
- int bus_for_each_dev(struct bus_type *bus, struct device *start,
- void *data, int (*fn)(struct device *, void *))
- {
- struct klist_iter i;
- struct device *dev;
- int error = 0;
- if (!bus)
- return -EINVAL;
- klist_iter_init_node(&bus->p->klist_devices, &i,
- (start ? &start->p->knode_bus : NULL));
- while ((dev = next_device(&i)) && !error)
- error = fn(dev, data); //遍历链表上每个设备,调用传来的函数(这里是__driver_attach)匹配
- klist_iter_exit(&i);
- return error;
- }
- static int __driver_attach(struct device *dev, void *data)
- {
- struct device_driver *drv = data;
- /*
- * Lock device and try to bind to it. We drop the error
- * here and always return 0, because we need to keep trying
- * to bind to devices and some drivers will return an error
- * simply if it didn't support the device.
- *
- * driver_probe_device() will spit a warning if there
- * is an error.
- */
- if (!driver_match_device(drv, dev)) //是否匹配,不匹配就返回,匹配就继续下面的操作(1)
- return 0;
- if (dev->parent) /* Needed for USB */
- down(&dev->parent->sem);
- down(&dev->sem);
- if (!dev->driver) //如果设备还没有关联驱动
- driver_probe_device(drv, dev); //关联驱动和设备(2)
- up(&dev->sem);
- if (dev->parent)
- up(&dev->parent->sem);
- return 0;
- }
(1)使用驱动总线上的match方法,检测设备和驱动是否匹配
- static inline int driver_match_device(struct device_driver *drv,
- struct device *dev)
- {
- return drv->bus->match ? drv->bus->match(dev, drv) : 1; //如果bus有match方法,则调用。否则返回1
- }
(2)关联设备和驱动函数
- /**
- * driver_probe_device - attempt to bind device & driver together
- * @drv: driver to bind a device to
- * @dev: device to try to bind to the driver
- *
- * This function returns -ENODEV if the device is not registered,
- * 1 if the device is bound sucessfully and 0 otherwise.
- *
- * This function must be called with @dev->sem held. When called for a
- * USB interface, @dev->parent->sem must be held as well.
- */
- int driver_probe_device(struct device_driver *drv, struct device *dev)
- {
- int ret = 0;
- if (!device_is_registered(dev)) //此设备是否已经注册
- return -ENODEV;
- pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
- drv->bus->name, __func__, dev_name(dev), drv->name);
- pm_runtime_get_noresume(dev);
- pm_runtime_barrier(dev);
- ret = really_probe(dev, drv); //看名字 真实的probe
- pm_runtime_put_sync(dev);
- return ret;
- }
- static int really_probe(struct device *dev, struct device_driver *drv)
- {
- int ret = 0;
- atomic_inc(&probe_count);
- pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
- drv->bus->name, __func__, drv->name, dev_name(dev));
- WARN_ON(!list_empty(&dev->devres_head));
- dev->driver = drv;
- if (driver_sysfs_add(dev)) { //此函数将在driver和device目录下创建相互的连接文件
- printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
- __func__, dev_name(dev));
- goto probe_failed;
- }
- if (dev->bus->probe) { //有bus上的probe则调用它
- ret = dev->bus->probe(dev);
- if (ret)
- goto probe_failed;
- } else if (drv->probe) { //否则若有驱动的probe则调用它
- ret = drv->probe(dev);
- if (ret)
- goto probe_failed;
- }
- driver_bound(dev);
- ret = 1;
- pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
- drv->bus->name, __func__, dev_name(dev), drv->name);
- goto done;
- probe_failed:
- devres_release_all(dev);
- driver_sysfs_remove(dev);
- dev->driver = NULL;
- if (ret != -ENODEV && ret != -ENXIO) {
- /* driver matched but the probe failed */
- printk(KERN_WARNING
- "%s: probe of %s failed with error %d\n",
- drv->name, dev_name(dev), ret);
- }
- /*
- * Ignore errors returned by ->probe so that the next driver can try
- * its luck.
- */
- ret = 0;
- done:
- atomic_dec(&probe_count);
- wake_up(&probe_waitqueue);
- return ret;
- }
上述函数的主要调用关系
driver_register
driver_find
bus_add_driver
kobject_init_and_add
driver_attach
bus_for_each_dev
__driver_attach
driver_match_device
driver_probe_device
really_probe
四、类
类是设备的高层视图,所有创建的类都将在sys/class目录中。类是系统向用户层导出信息的一个不错的方法。
类结构的定义
- struct class {
- const char *name;
- struct module *owner;
- struct class_attribute *class_attrs;
- struct device_attribute *dev_attrs;
- struct kobject *dev_kobj;
- int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
- char *(*devnode)(struct device *dev, mode_t *mode);
- void (*class_release)(struct class *class);
- void (*dev_release)(struct device *dev);
- int (*suspend)(struct device *dev, pm_message_t state);
- int (*resume)(struct device *dev);
- const struct dev_pm_ops *pm;
- struct class_private *p;
- };
创建类的函数如下
- struct class *__class_create(struct module *owner, const char *name,
- struct lock_class_key *key)
- {
- struct class *cls;
- int retval;
- cls = kzalloc(sizeof(*cls), GFP_KERNEL);
- if (!cls) {
- retval = -ENOMEM;
- goto error;
- }
- cls->name = name;
- cls->owner = owner;
- cls->class_release = class_create_release;
- retval = __class_register(cls, key);
- if (retval)
- goto error;
- return cls;
- error:
- kfree(cls);
- return ERR_PTR(retval);
- }
创建一个类是创建了一个容器,我们最主要的还是创建类下面的设备。在类下创建设备的函数是。
在旧的linux版本中有专门创建类设备的函数class_device_create,而新的版本中没有了(我现在看的2.6.31就没有)。
我们先看旧版本的
类设备结构定义
- struct class_device {
- struct list_head node;
- struct kobject kobj;
- struct class * class; /* required */
- dev_t devt; /* dev_t, creates the sysfs "dev" */
- struct class_device_attribute *devt_attr;
- struct class_device_attribute uevent_attr;
- struct device * dev; /* not necessary, but nice to have */
- void * class_data; /* class-specific data */
- struct class_device *parent; /* parent of this child device, if there is one */
- void (*release)(struct class_device *dev);
- int (*uevent)(struct class_device *dev, char **envp,
- int num_envp, char *buffer, int buffer_size);
- char class_id[BUS_ID_SIZE]; /* unique to this class */
- };
创建类设备函数class_device_create,此函数调用关系如下
class_device_create
class_device_initialize
class_device_add
新版本的linux没有了class_device,class_device_create等。可以直接使用device_create,调用顺序为
device_create
device_create_vargs
device_register
device_initialize
device_add
阅读(414) | 评论(0) | 转发(0) |