网站地图 业务咨询:400-601-6788   联系我们
开放式开发平台
资料下载
教学培训
常见问题解答
技术文摘
 

400-601-6788
技术咨询: 点击这里和我在线联系
     线上留言      伙伴申请
     投递简历
 
  您的位置:首页 > 技术支持 > 技术文摘 >

 

GSC3280的ADC子系统驱动模型(三)----class的使用 

 

 

       一个类是一个设备的高层视图,它抽象掉了底层的实现细节。例如,在驱动层面时,你可能会见到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.   

5.      struct class_attribute        *class_attrs;

6.      struct device_attribute        *dev_attrs;

7.      struct bin_attribute        *dev_bin_attrs;

8.      struct kobject            *dev_kobj;

9.   

10.    int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);

11.    char *(*devnode)(struct device *dev, mode_t *mode);

12. 

13.    void (*class_release)(struct class *class);

14.    void (*dev_release)(struct device *dev);

15. 

16.    int (*suspend)(struct device *dev, pm_message_t state);

17.    int (*resume)(struct device *dev);

18. 

19.    const struct kobj_ns_type_operations *ns_type;

20.    const void *(*namespace)(struct device *dev);

21. 

22.    const struct dev_pm_ops *pm;

23. 

24.    struct subsys_private *p;

25.};

26.#define class_create(owner, name)        \

27.({                        \

28.    static struct lock_class_key __key;    \

29.    __class_create(owner, name, &__key);    \

30.})

31.struct class *__class_create(struct module *owner, const char *name,

32.             struct lock_class_key *key)

33.{

34.    struct class *cls;

35.    int retval;

36. 

37.    cls = kzalloc(sizeof(*cls), GFP_KERNEL);

38.    if (!cls) {

39.        retval = -ENOMEM;

40.        goto error;

41.    }

42. 

43.    cls->name = name;

44.    cls->owner = owner;

45.    cls->class_release = class_create_release;

46. 

47.    retval = __class_register(cls, key);

48.    if (retval)

49.        goto error;

50. 

51.    return cls;

52. 

53.error:

54.    kfree(cls);

55.    return ERR_PTR(retval);

56.}

57.int __class_register(struct class *cls, struct lock_class_key *key)

58.{

59.    struct subsys_private *cp;

60.    int error;

61. 

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

63. 

64.    cp = kzalloc(sizeof(*cp), GFP_KERNEL);

65.    if (!cp)

66.        return -ENOMEM;

67.    klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put);

68.    INIT_LIST_HEAD(&cp->class_interfaces);

69.    kset_init(&cp->glue_dirs);

70.    __mutex_init(&cp->class_mutex, "struct class mutex", key);

71.    error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name);

72.    if (error) {

73.        kfree(cp);

74.        return error;

75.    }

76. 

77.    /* set the default /sys/dev directory for devices of this class */

78.    if (!cls->dev_kobj)

79.        cls->dev_kobj = sysfs_dev_char_kobj;

80. 

81.#if defined(CONFIG_BLOCK)

82.    /* let the block class directory show up in the root of sysfs */

83.    if (!sysfs_deprecated || cls != &block_class)

84.        cp->subsys.kobj.kset = class_kset;

85.#else

86.    cp->subsys.kobj.kset = class_kset;

87.#endif

88.    cp->subsys.kobj.ktype = &class_ktype;

89.    cp->class = cls;

90.    cls->p = cp;

91. 

92.    error = kset_register(&cp->subsys);

93.    if (error) {

94.        kfree(cp);

95.        return error;

96.    }

97.    error = add_class_attrs(class_get(cls));

98.    class_put(cls);

99.    return error;

100.         }

  说明:
    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. 

24.    dev = get_device(dev);

25.    if (!dev)

26.        goto done;

27. 

28.    if (!dev->p) {

29.        error = device_private_init(dev);

30.        if (error)

31.            goto done;

32.    }

33. 

34.    /*

35.     * for statically allocated devices, which should all be converted

36.     * some day, we need to initialize the name. We prevent reading back

37.     * the name, and force the use of dev_name()

38.     */

39.    if (dev->init_name) {

40.        dev_set_name(dev, "%s", dev->init_name);

41.        dev->init_name = NULL;

42.    }

43. 

44.    if (!dev_name(dev)) {

45.        error = -EINVAL;

46.        goto name_error;

47.    }

48. 

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

50. 

51.    parent = get_device(dev->parent);

52.    setup_parent(dev, parent);

53. 

54.    /* use parent numa_node */

55.    if (parent)

56.        set_dev_node(dev, dev_to_node(parent));

57. 

58.    /* first, register with generic layer. */

59.    /* we require the name to be set before, and pass NULL */

60.    error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);

61.    if (error)

62.        goto Error;

63. 

64.    /* notify platform of device entry */

65.    if (platform_notify)

66.        platform_notify(dev);

67. 

68.    error = device_create_file(dev, &uevent_attr);

69.    if (error)

70.        goto attrError;

71. 

72.    if (MAJOR(dev->devt)) {

73.        error = device_create_file(dev, &devt_attr);

74.        if (error)

75.            goto ueventattrError;

76. 

77.        error = device_create_sys_dev_entry(dev);

78.        if (error)

79.            goto devtattrError;

80. 

81.        devtmpfs_create_node(dev);

82.    }

83. 

84.    error = device_add_class_symlinks(dev);

85.    if (error)

86.        goto SymlinkError;

87.    error = device_add_attrs(dev);

88.    if (error)

89.        goto AttrsError;

90.    error = bus_add_device(dev);

91.    if (error)

92.        goto BusError;

93.    error = dpm_sysfs_add(dev);

94.    if (error)

95.        goto DPMError;

96.    device_pm_add(dev);

97. 

98.    /* Notify clients of device addition. This call must come

99.     * after dpm_sysf_add() and before kobject_uevent().

100.              */

101.             if (dev->bus)

102.                 blocking_notifier_call_chain(&dev->bus->p->bus_notifier,

103.                              BUS_NOTIFY_ADD_DEVICE, dev);

104.          

105.             kobject_uevent(&dev->kobj, KOBJ_ADD);

106.             bus_probe_device(dev);

107.             if (parent)

108.                 klist_add_tail(&dev->p->knode_parent,

109.                      &parent->p->klist_children);

110.          

111.             if (dev->class) {

112.                 mutex_lock(&dev->class->p->class_mutex);

113.                 /* tie the class to the device */

114.                 klist_add_tail(&dev->knode_class,

115.                      &dev->class->p->klist_devices);

116.          

117.                 /* notify any interfaces that the device is here */

118.                 list_for_each_entry(class_intf,

119.                          &dev->class->p->class_interfaces, node)

120.                     if (class_intf->add_dev)

121.                         class_intf->add_dev(dev, class_intf);

122.                 mutex_unlock(&dev->class->p->class_mutex);

123.             }

124.         done:

125.             put_device(dev);

126.             return error;

127.          DPMError:

128.             bus_remove_device(dev);

129.          BusError:

130.             device_remove_attrs(dev);

131.          AttrsError:

132.             device_remove_class_symlinks(dev);

133.          SymlinkError:

134.             if (MAJOR(dev->devt))

135.                 devtmpfs_delete_node(dev);

136.             if (MAJOR(dev->devt))

137.                 device_remove_sys_dev_entry(dev);

138.          devtattrError:

139.             if (MAJOR(dev->devt))

140.                 device_remove_file(dev, &devt_attr);

141.          ueventattrError:

142.             device_remove_file(dev, &uevent_attr);

143.          attrError:

144.             kobject_uevent(&dev->kobj, KOBJ_REMOVE);

145.             kobject_del(&dev->kobj);

146.          Error:

147.             cleanup_device_parent(dev);

148.             if (parent)

149.                 put_device(parent);

150.         name_error:

151.             kfree(dev->p);

152.             dev->p = NULL;

153.             goto done;

154.         }

    说明:

       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.   

7.      if (class) {

8.          error = device_add_attributes(dev, class->dev_attrs);

9.          if (error)

10.            return error;

11.        error = device_add_bin_attributes(dev, class->dev_bin_attrs);

12.        if (error)

13.            goto err_remove_class_attrs;

14.    }

15. 

16.    if (type) {

17.        error = device_add_groups(dev, type->groups);

18.        if (error)

19.            goto err_remove_class_bin_attrs;

20.    }

21. 

22.    error = device_add_groups(dev, dev->groups);

23.    if (error)

24.        goto err_remove_type_groups;

25. 

26.    return 0;

27. 

28. err_remove_type_groups:

29.    if (type)

30.        device_remove_groups(dev, type->groups);

31. err_remove_class_bin_attrs:

32.    if (class)

33.        device_remove_bin_attributes(dev, class->dev_bin_attrs);

34. err_remove_class_attrs:

35.    if (class)

36.        device_remove_attributes(dev, class->dev_attrs);

37. 

38.    return error;

39.}

 说明:

    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.   

7.      if (attrs) {

8.          for (i = 0; attr_name(attrs[i]); i++) {

9.              error = device_create_file(dev, &attrs[i]);

10.            if (error)

11.                break;

12.        }

13.        if (error)

14.            while (--i >= 0)

15.                device_remove_file(dev, &attrs[i]);

16.    }

17.    return error;

18.}

 说明:

     1) 最后是调用device_create_file(dev, &attrs[i]);产生文件的。此函数在其他文章中会介绍。

 

原文参见:http://blog.chinaunix.net/uid-25445243-id-4038871.html

 
联系我们  总机:010-82357611 传真:010-82357612
Copyright 2011 © 北京神州龙芯集成电路设计有限公司版权所有  京ICP备05080070号