Chinaunix首页 | 论坛 | 博客
  • 博客访问: 369318
  • 博文数量: 159
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 182
  • 用 户 组: 普通用户
  • 注册时间: 2013-11-02 10:42
文章分类

全部博文(159)

文章存档

2015年(18)

2014年(132)

2013年(9)

分类: 嵌入式

2014-08-11 19:36:09

        一个类是一个设备的高层视图,它抽象掉了底层的实现细节。例如,在驱动层面时,你可能会见到SCSI磁盘或者ATA磁盘;但在类层面时,它们都是磁盘。类允许用户空间基于它们做什么来使用设备,而不是它们如何被连接或者它们如何工作。
        在《GSC3280的ADC子系统驱动模型(一)》的3.1,程序adc_class = class_create(THIS_MODULE, "adc");产生一个class,class_create()函数如下:

点击(此处)折叠或打开

  1. struct class {
  2.     const char        *name;
  3.     struct module        *owner;

  4.     struct class_attribute        *class_attrs;
  5.     struct device_attribute        *dev_attrs;
  6.     struct bin_attribute        *dev_bin_attrs;
  7.     struct kobject            *dev_kobj;

  8.     int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
  9.     char *(*devnode)(struct device *dev, mode_t *mode);

  10.     void (*class_release)(struct class *class);
  11.     void (*dev_release)(struct device *dev);

  12.     int (*suspend)(struct device *dev, pm_message_t state);
  13.     int (*resume)(struct device *dev);

  14.     const struct kobj_ns_type_operations *ns_type;
  15.     const void *(*namespace)(struct device *dev);

  16.     const struct dev_pm_ops *pm;

  17.     struct subsys_private *p;
  18. };
  19. #define class_create(owner, name)        \
  20. ({                        \
  21.     static struct lock_class_key __key;    \
  22.     __class_create(owner, name, &__key);    \
  23. })
  24. struct class *__class_create(struct module *owner, const char *name,
  25.              struct lock_class_key *key)
  26. {
  27.     struct class *cls;
  28.     int retval;

  29.     cls = kzalloc(sizeof(*cls), GFP_KERNEL);
  30.     if (!cls) {
  31.         retval = -ENOMEM;
  32.         goto error;
  33.     }

  34.     cls->name = name;
  35.     cls->owner = owner;
  36.     cls->class_release = class_create_release;

  37.     retval = __class_register(cls, key);
  38.     if (retval)
  39.         goto error;

  40.     return cls;

  41. error:
  42.     kfree(cls);
  43.     return ERR_PTR(retval);
  44. }
  45. int __class_register(struct class *cls, struct lock_class_key *key)
  46. {
  47.     struct subsys_private *cp;
  48.     int error;

  49.     pr_debug("device class '%s': registering\n", cls->name);

  50.     cp = kzalloc(sizeof(*cp), GFP_KERNEL);
  51.     if (!cp)
  52.         return -ENOMEM;
  53.     klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put);
  54.     INIT_LIST_HEAD(&cp->class_interfaces);
  55.     kset_init(&cp->glue_dirs);
  56.     __mutex_init(&cp->class_mutex, "struct class mutex", key);
  57.     error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name);
  58.     if (error) {
  59.         kfree(cp);
  60.         return error;
  61.     }

  62.     /* set the default /sys/dev directory for devices of this class */
  63.     if (!cls->dev_kobj)
  64.         cls->dev_kobj = sysfs_dev_char_kobj;

  65. #if defined(CONFIG_BLOCK)
  66.     /* let the block class directory show up in the root of sysfs */
  67.     if (!sysfs_deprecated || cls != &block_class)
  68.         cp->subsys.kobj.kset = class_kset;
  69. #else
  70.     cp->subsys.kobj.kset = class_kset;
  71. #endif
  72.     cp->subsys.kobj.ktype = &class_ktype;
  73.     cp->class = cls;
  74.     cls->p = cp;

  75.     error = kset_register(&cp->subsys);
  76.     if (error) {
  77.         kfree(cp);
  78.         return error;
  79.     }
  80.     error = add_class_attrs(class_get(cls));
  81.     class_put(cls);
  82.     return error;
  83. }
        说明:
        1) class_create()函数是一个宏定义,具体调用了__class_create()函数。
        2) __class_create()函数首先申请了一个class结构体内存,然后对其结构体成员变量赋值,最后调用__class_register()函数注册类。
        3) __class_register()函数中,首先申请了结构体subsys_private内存,从class结构体成员可以看到,subsys_private是其一个成员指针。
        4) 然后就是对subsys_private的成员变量初始化,注册subsys的kset,增加类属性等。
        在《GSC3280的ADC子系统驱动模型(二)》的2.1中,介绍了sysfs的初始化,程序如下:

点击(此处)折叠或打开

  1. void __init adc_sysfs_init(struct class *adc_class)
  2. {
  3.     adc_class->dev_attrs = adc_attrs;
  4. }
        说明:
        1) 此处的类即是上面我们使用class_creat()创建的类。
        2) 对类中的设备属性赋值,下面会讲述。
        在《GSC3280的ADC子系统驱动模型(一)》的3.2中,首先使用程序adc->dev.class = adc_class;将我们上面定义的类赋值给dev中的类,然后程序err = device_register(&adc->dev);注册这个设备,在这里的设备注册函数中,我们主要关注设备结构体中类的注册。device_register()函数如下:

点击(此处)折叠或打开

  1. int device_register(struct device *dev)
  2. {
  3.     device_initialize(dev);
  4.     return device_add(dev);
  5. }
  6. void device_initialize(struct device *dev)
  7. {
  8.     dev->kobj.kset = devices_kset;
  9.     kobject_init(&dev->kobj, &device_ktype);
  10.     INIT_LIST_HEAD(&dev->dma_pools);
  11.     mutex_init(&dev->mutex);
  12.     lockdep_set_novalidate_class(&dev->mutex);
  13.     spin_lock_init(&dev->devres_lock);
  14.     INIT_LIST_HEAD(&dev->devres_head);
  15.     device_pm_init(dev);
  16.     set_dev_node(dev, -1);
  17. }
  18. int device_add(struct device *dev)
  19. {
  20.     struct device *parent = NULL;
  21.     struct class_interface *class_intf;
  22.     int error = -EINVAL;

  23.     dev = get_device(dev);
  24.     if (!dev)
  25.         goto done;

  26.     if (!dev->p) {
  27.         error = device_private_init(dev);
  28.         if (error)
  29.             goto done;
  30.     }

  31.     /*
  32.      * for statically allocated devices, which should all be converted
  33.      * some day, we need to initialize the name. We prevent reading back
  34.      * the name, and force the use of dev_name()
  35.      */
  36.     if (dev->init_name) {
  37.         dev_set_name(dev, "%s", dev->init_name);
  38.         dev->init_name = NULL;
  39.     }

  40.     if (!dev_name(dev)) {
  41.         error = -EINVAL;
  42.         goto name_error;
  43.     }

  44.     pr_debug("device: '%s': %s\n", dev_name(dev), __func__);

  45.     parent = get_device(dev->parent);
  46.     setup_parent(dev, parent);

  47.     /* use parent numa_node */
  48.     if (parent)
  49.         set_dev_node(dev, dev_to_node(parent));

  50.     /* first, register with generic layer. */
  51.     /* we require the name to be set before, and pass NULL */
  52.     error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
  53.     if (error)
  54.         goto Error;

  55.     /* notify platform of device entry */
  56.     if (platform_notify)
  57.         platform_notify(dev);

  58.     error = device_create_file(dev, &uevent_attr);
  59.     if (error)
  60.         goto attrError;

  61.     if (MAJOR(dev->devt)) {
  62.         error = device_create_file(dev, &devt_attr);
  63.         if (error)
  64.             goto ueventattrError;

  65.         error = device_create_sys_dev_entry(dev);
  66.         if (error)
  67.             goto devtattrError;

  68.         devtmpfs_create_node(dev);
  69.     }

  70.     error = device_add_class_symlinks(dev);
  71.     if (error)
  72.         goto SymlinkError;
  73.     error = device_add_attrs(dev);
  74.     if (error)
  75.         goto AttrsError;
  76.     error = bus_add_device(dev);
  77.     if (error)
  78.         goto BusError;
  79.     error = dpm_sysfs_add(dev);
  80.     if (error)
  81.         goto DPMError;
  82.     device_pm_add(dev);

  83.     /* Notify clients of device addition. This call must come
  84.      * after dpm_sysf_add() and before kobject_uevent().
  85.      */
  86.     if (dev->bus)
  87.         blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
  88.                      BUS_NOTIFY_ADD_DEVICE, dev);

  89.     kobject_uevent(&dev->kobj, KOBJ_ADD);
  90.     bus_probe_device(dev);
  91.     if (parent)
  92.         klist_add_tail(&dev->p->knode_parent,
  93.              &parent->p->klist_children);

  94.     if (dev->class) {
  95.         mutex_lock(&dev->class->p->class_mutex);
  96.         /* tie the class to the device */
  97.         klist_add_tail(&dev->knode_class,
  98.              &dev->class->p->klist_devices);

  99.         /* notify any interfaces that the device is here */
  100.         list_for_each_entry(class_intf,
  101.                  &dev->class->p->class_interfaces, node)
  102.             if (class_intf->add_dev)
  103.                 class_intf->add_dev(dev, class_intf);
  104.         mutex_unlock(&dev->class->p->class_mutex);
  105.     }
  106. done:
  107.     put_device(dev);
  108.     return error;
  109.  DPMError:
  110.     bus_remove_device(dev);
  111.  BusError:
  112.     device_remove_attrs(dev);
  113.  AttrsError:
  114.     device_remove_class_symlinks(dev);
  115.  SymlinkError:
  116.     if (MAJOR(dev->devt))
  117.         devtmpfs_delete_node(dev);
  118.     if (MAJOR(dev->devt))
  119.         device_remove_sys_dev_entry(dev);
  120.  devtattrError:
  121.     if (MAJOR(dev->devt))
  122.         device_remove_file(dev, &devt_attr);
  123.  ueventattrError:
  124.     device_remove_file(dev, &uevent_attr);
  125.  attrError:
  126.     kobject_uevent(&dev->kobj, KOBJ_REMOVE);
  127.     kobject_del(&dev->kobj);
  128.  Error:
  129.     cleanup_device_parent(dev);
  130.     if (parent)
  131.         put_device(parent);
  132. name_error:
  133.     kfree(dev->p);
  134.     dev->p = NULL;
  135.     goto done;
  136. }
        说明:
        1) device_register()函数首先调用device_initialize(dev);对dev成员初始化。
        2) 然后调用device_add()函数增加设备。其中的device_add_attrs(dev)函数完成对类成员中的设备属性初始化,具体程序如下:

点击(此处)折叠或打开

  1. static int device_add_attrs(struct device *dev)
  2. {
  3.     struct class *class = dev->class;
  4.     const struct device_type *type = dev->type;
  5.     int error;

  6.     if (class) {
  7.         error = device_add_attributes(dev, class->dev_attrs);
  8.         if (error)
  9.             return error;
  10.         error = device_add_bin_attributes(dev, class->dev_bin_attrs);
  11.         if (error)
  12.             goto err_remove_class_attrs;
  13.     }

  14.     if (type) {
  15.         error = device_add_groups(dev, type->groups);
  16.         if (error)
  17.             goto err_remove_class_bin_attrs;
  18.     }

  19.     error = device_add_groups(dev, dev->groups);
  20.     if (error)
  21.         goto err_remove_type_groups;

  22.     return 0;

  23.  err_remove_type_groups:
  24.     if (type)
  25.         device_remove_groups(dev, type->groups);
  26.  err_remove_class_bin_attrs:
  27.     if (class)
  28.         device_remove_bin_attributes(dev, class->dev_bin_attrs);
  29.  err_remove_class_attrs:
  30.     if (class)
  31.         device_remove_attributes(dev, class->dev_attrs);

  32.     return error;
  33. }
        说明:
        1) 由上面可知,dev成员中有class成员,但是class中只有对dev_attrs赋值了,dev成员中没有groups成员,所以此处执行的函数为device_add_attributes(dev, class->dev_attrs),程序如下:

点击(此处)折叠或打开

  1. static int device_add_attributes(struct device *dev,
  2.                  struct device_attribute *attrs)
  3. {
  4.     int error = 0;
  5.     int i;

  6.     if (attrs) {
  7.         for (i = 0; attr_name(attrs[i]); i++) {
  8.             error = device_create_file(dev, &attrs[i]);
  9.             if (error)
  10.                 break;
  11.         }
  12.         if (error)
  13.             while (--i >= 0)
  14.                 device_remove_file(dev, &attrs[i]);
  15.     }
  16.     return error;
  17. }
        说明:
        1) 最后是调用device_create_file(dev, &attrs[i]);产生文件的。此函数在其他文章中会介绍。
阅读(890) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~