drivers\base\class.c

 

小结:

 

这个文件中,声明了类子系统class_subsys,作为所有类kobject的kset

声明了class_obj_subsys子系统,作为所有类设备kobject的kset

类设备class_device的父类是class,或则说,class是一个容器,里面包含了很多class_device

 

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

函数列表:

 

int   class_create_file(struct class * cls,       const struct class_attribute * attr)

void       class_remove_file(struct class * cls,     const struct class_attribute * attr)

创建/删除指定类的属性文件

 

@@@@@     类操作

int   class_register(struct class * cls)

类的注册,具体操作如下:

//1、清空类的子设备,设备,接口三个链表

//2、设置类子系统的名字,将类cls->subsys.kobj.kset挂到class_subsys子系统上

//3、为类创建属性文件

 

void class_unregister(struct class * cls)

类的反注册

 

struct class     *class_create(struct module *owner,    const char *name)

类的创建,具体操作如下:

//1、申请一块内存用于保存类结构体

//2、设置类的名字,所有者,关联release函数

//3、调用class_register函数注册类

 

void class_destroy(struct class *cls)

类销毁,其核心操作是class_unregister

 

@@@@@     类设备操作

void       class_device_initialize(struct class_device    *class_dev)

类设备的初始化操作

//1、将类设备的kset挂到class_obj_subsys子系统下

//2、类设备kobj初始化

//3、挂空类设备的节点class_dev->node

 

int   class_device_add(struct class_device *class_dev)

//类设备的添加,具体操作如下:

//1、获取类设备,检查其合法性。

//2、设置类的kobj名字,设置其父设备,创建属性文件

//3、kobject_uevent(&class_dev->kobj, KOBJ_ADD);

//4、将类设备节点class_dev->node加到父类链表parent_class->children中

//5、调用父类所有接口的add函数,添加该类设备

 

int   class_device_register(struct class_device *class_dev)

类设备的注册,实际就是调用上面两个函数,先初始化,在添加

 

struct class_device *class_device_create(struct class *cls,

                                    struct class_device *parent,

                                    dev_t devt,

                                    struct device *device,

                                    const char *fmt, ...)

类设备的创建,先根据参数新建并设置类设备,然后调用class_device_register进行注册

 

void       class_device_del(struct class_device *class_dev)

类设备的删除,是class_device_add的反操作

 

void       class_device_unregister(struct class_device *class_dev)

类设备的反注册,是类设备注册的反函数,直接调用了class_device_del函数

 

void       class_device_destroy(struct class *cls, dev_t devt)

类设备销毁,具体操作是根据指定的设备号从cls的类设备链表中找到类设备,然后运行反注册函数

 

@@@@@     类接口操作

int   class_interface_register(struct class_interface      *class_intf)

//类接口注册,具体操作是将接口的节点挂到所属类的接口链表中,然后遍历类的类设备链表和设备链表,分别调用add和add_dev函数

 

void       class_interface_unregister(struct class_interface *class_intf)

类接口反注册,同注册,只是分别调用的是remove和remove_dev函数

 

@@@@@

int   classes_init(void)

类的初始化,系统自动调用,操作是注册class_subsys子系统,设置类设备的kset和obj的父设备

 

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//根据属性获取类属性结构体, 根据obj获取类结构体

#define   to_class_attr(_attr)        container_of(_attr, struct class_attribute, attr)

#define   to_class(obj)                container_of(obj, struct class, subsys.kobj)

 

struct class_attribute {

       struct attribute        attr;

       ssize_t (*show)(struct class *, char * buf);

       ssize_t (*store)(struct class *, const char * buf, size_t count);

};

 

//这个结构体在SI中不好关联,实际是在include/linux/device.h中

struct class {

       const char              * name;                 //类名

       struct module         * owner;                //对应模块

 

       struct kset              subsys;                  //对应的子系统subsystem

       struct list_head       children;                //class_device链表

       struct list_head       devices;

       struct list_head       interfaces;              //class_interface链表

       struct kset              class_dirs;

       struct semaphore    sem;

 

       struct class_attribute             * class_attrs;

       struct class_device_attribute   * class_dev_attrs;

       struct device_attribute           * dev_attrs;

 

       int   (*uevent)(struct class_device *dev, struct kobj_uevent_env *env);

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

 

       void (*release)(struct class_device *dev);

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

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

 

       int   (*suspend)(struct device *, pm_message_t state);

       int   (*resume)(struct device *);

};

 

//类设备,class是一个容器,里面包含了很多class_device

struct class_device {

       struct list_head       node;

 

       struct kobject         kobj;                     //kobj

       struct class             * class;                  //所属的类

       dev_t                    devt;                            //设备号

       struct device          * dev;                   //若存在,创建到/sys/devices相应入口的符号链接

       void               * class_data;                 //私有数据

       struct class_device  *parent;                 //父设备

       struct attribute_group  ** groups;              //属性组

       void (*release)(struct class_device *dev);

       int   (*uevent)(struct class_device *dev, struct kobj_uevent_env *env);

       char class_id[BUS_ID_SIZE];             //类名

};

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//调用类属性的show函数

static ssize_t    class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)

{

       struct class_attribute      * class_attr = to_class_attr(attr);           //获取类属性

       struct class * dc = to_class(kobj);                                            //获取类

       ssize_t ret = -EIO;

 

       if (class_attr->show)             ret = class_attr->show(dc, buf);

       return ret;

}

 

//调用类属性的store函数

static ssize_t    class_attr_store(struct kobject * kobj, struct attribute * attr,

               const char * buf, size_t count)

 

//调用类的release函数

static void      class_release(struct kobject * kobj)

{

       struct class *class = to_class(kobj);

 

       if (class->class_release)         class->class_release(class);

       else         //打印类没有release函数    

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//封装

static struct sysfs_ops    class_sysfs_ops = {

       .show      = class_attr_show,

       .store      = class_attr_store,

};

 

static struct kobj_type   class_ktype = {

       .sysfs_ops       = &class_sysfs_ops,

       .release           = class_release,

};

 

//声明class_subsys

static      decl_subsys(class, &class_ktype, NULL);

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//创建类的属性关联文件

int   class_create_file(struct class * cls,       const struct class_attribute * attr)

{

       int error;

       if (cls)    error = sysfs_create_file(&cls->subsys.kobj,       &attr->attr);

       else         error = -EINVAL;

       return error;

}

 

//删除类属性的关联文件

void       class_remove_file(struct class * cls,     const struct class_attribute * attr)

{

       if (cls)     sysfs_remove_file(&cls->subsys.kobj, &attr->attr);

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类引用,释放

static struct class    *class_get(struct class *cls)

{

       if (cls)     return container_of(kset_get(&cls->subsys), struct class, subsys);

       return     NULL;

}

 

static void      class_put(struct class * cls)

{

       if (cls)     kset_put(&cls->subsys);

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//一个类中可以包含一组属性,这里为类创建所有的属性文件

static int        add_class_attrs(struct class * cls)

{

       int i;

       int error = 0;

 

       //类属性已设置,为类添加所有的属性文件

       if (cls->class_attrs) {

              for (i = 0; attr_name(cls->class_attrs[i]); i++) {

                     error = class_create_file(cls,&cls->class_attrs[i]);

                     if (error)        goto Err;

              }

       }

 Done:

       return error;

 Err:

       while (--i >= 0)      class_remove_file(cls,&cls->class_attrs[i]);

       goto Done;

}

 

//删除与类关联的所有属性文件,也是add的错误时处理

static void      remove_class_attrs(struct class * cls)

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类的注册,主要过程如下:

//1、清空类的子设备,设备,接口三个链表

//2、设置类子系统的名字,将类cls->subsys.kobj.kset挂到class_subsys子系统上

//3、为类创建属性文件

int   class_register(struct class * cls)

{

       int error;

      

       INIT_LIST_HEAD(&cls->children);           //清空类的子设备链表

       INIT_LIST_HEAD(&cls->devices);            //清空类的设备链表

       INIT_LIST_HEAD(&cls->interfaces);         //清空类的接口链表

       kset_init(&cls->class_dirs);                        //初始化kset(类的父节点)

       init_MUTEX(&cls->sem);                          //信号量

       error = kobject_set_name(&cls->subsys.kobj, "%s", cls->name);              //类子系统命名

       if (error) return error;

 

       cls->subsys.kobj.kset = &class_subsys;        //设置类节点的父节点为class_subsys

 

       error = subsystem_register(&cls->subsys);   //子系统注册(kobject文件中实现)

       if (!error) {    //注册成功

              error = add_class_attrs(class_get(cls));  //为类创建属性文件

              class_put(cls);

       }

       return error;

}

 

//类的反注册,类注册的反过程

void class_unregister(struct class * cls)

{

       remove_class_attrs(cls);

       subsystem_unregister(&cls->subsys);

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类的释放函数

static void      class_create_release(struct class *cls)

{

       kfree(cls);

}

 

//类设备的释放函数

static void class_device_create_release(struct class_device *class_dev)

{

       kfree(class_dev);

}

 

//类设备的uevent函数,直接返回0

static int class_device_create_uevent(struct class_device *class_dev,

                                  struct kobj_uevent_env *env)

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类的创建,具体过程如下:

//1、申请一块内存用于保存类结构体

//2、设置类的名字,所有者,关联release函数

//3、调用class_register函数注册类

struct class     *class_create(struct module *owner,    const char *name)

{

       struct class *cls;

       int retval;

 

       cls = kzalloc(sizeof(*cls), GFP_KERNEL);         //申请一块内存空间

       if (!cls) {                             //内存申请失败

              retval = -ENOMEM;

              goto error;

       }

 

       //设置类的名字,所有者,release函数

       cls->name = name;

       cls->owner = owner;

       cls->class_release = class_create_release;

       cls->release = class_device_create_release;

 

       //类注册

       retval = class_register(cls);

       if (retval)              goto error;

 

       return     cls;

 

error:

       kfree(cls);

       return     ERR_PTR(retval);

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类销毁,其核心操作是类的反注册

void class_destroy(struct class *cls)

{

       if ((cls == NULL) || (IS_ERR(cls)))            return;

       class_unregister(cls);

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类设备创建/删除属性文件

int   class_device_create_file(

       struct class_device        * class_dev,

       const struct class_device_attribute        * attr)

{

       int error = -EINVAL;

       if (class_dev)         error = sysfs_create_file(&class_dev->kobj, &attr->attr);

       return error;

}

 

void class_device_remove_file(struct class_device * class_dev,

                           const struct class_device_attribute * attr)

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类设备创建二进制的属性文件

int class_device_create_bin_file(struct class_device *class_dev,

                             struct bin_attribute *attr)

{

       int error = -EINVAL;

       if (class_dev)  error = sysfs_create_bin_file(&class_dev->kobj, attr);

       return error;

}

 

void class_device_remove_bin_file(struct class_device *class_dev,

                              struct bin_attribute *attr)

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

声明class_obj_subsys模块

 

//调用类设备属性中的show/store函数

static ssize_t   

class_device_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)

{

       struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr);

       struct class_device * cd = to_class_dev(kobj);

      

       if (class_dev_attr->show)      ret = class_dev_attr->show(cd, buf);

       return ret;

}

 

static ssize_t

class_device_attr_store(struct kobject * kobj, struct attribute * attr,

                     const char * buf, size_t count)

 

//操作结构体

static struct sysfs_ops    class_dev_sysfs_ops = {

       .show      = class_device_attr_show,

       .store      = class_device_attr_store,

};

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类设备的释放函数,调用类设备,或类的release函数

static void class_dev_release(struct kobject * kobj)

{

       struct class_device *cd = to_class_dev(kobj);

       struct class * cls = cd->class;

 

       if (cd->release)             cd->release(cd);

       else if (cls->release)       cls->release(cd);

       else        //打印警告:类设备和类都没指定release函数

}

 

static struct kobj_type   class_device_ktype = {

       .sysfs_ops       = &class_dev_sysfs_ops,       //上方一点

       .release           = class_dev_release,

};

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类uevent的过滤函数,kobj的ktype是指定的ktype,且kobj的宿主有指定class,有效,返回1

static int        class_uevent_filter(struct kset *kset,    struct kobject *kobj)

{

       struct kobj_type     *ktype = get_ktype(kobj);

 

       if (ktype == &class_device_ktype) {

              struct class_device        *class_dev = to_class_dev(kobj);

              if (class_dev->class)             return 1;

       }

       return 0;

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//返回类设备的类名

static const char     *class_uevent_name(struct kset *kset, struct kobject *kobj)

{

       struct class_device        *class_dev = to_class_dev(kobj);

       return     class_dev->class->name;

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

static int               class_uevent(

       struct kset                    *kset,

       struct kobject                      *kobj,

       struct kobj_uevent_env *env)

{

       struct class_device        *class_dev = to_class_dev(kobj);   //获取类设备

       struct device                 *dev = class_dev->dev;                //获取类设备对应的设备

       int retval = 0;

 

       //类设备的主设备号不为0,添加设备号信息

       if (MAJOR(class_dev->devt)) {

              add_uevent_var(env, "MAJOR=%u", MAJOR(class_dev->devt));

              add_uevent_var(env, "MINOR=%u", MINOR(class_dev->devt));

       }

 

       //关联的设备存在

       if (dev) {

              //添加设备路径信息

              const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);

              if (path) {

                     add_uevent_var(env, "PHYSDEVPATH=%s", path);

                     kfree(path);

              }

 

              //添加总线名和设备驱动名

              if (dev->bus)  add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);

              if (dev->driver)add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name);

       }

 

       //执行类设备的uevent函数(先类设备,在类自带的)

       if (class_dev->uevent) {

              retval = class_dev->uevent(class_dev, env);

       } else if (class_dev->class->uevent) {

              retval = class_dev->class->uevent(class_dev, env);

       }

 

       return retval;

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//操作函数关联

static struct kset_uevent_ops               class_uevent_ops = {

       .filter =   class_uevent_filter,

       .name =   class_uevent_name,

       .uevent = class_uevent,

};

 

//声明class_obj_subsys子系统

static      decl_subsys(class_obj,   &class_device_ktype,    &class_uevent_ops);

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//同class_device_add_attrs,为类设备添加属性

static int        class_device_add_attrs(struct class_device * cd)

 

//删除类设备的属性文件

static void class_device_remove_attrs(struct class_device * cd)

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类设备创建组属性

static int        class_device_add_groups(struct class_device * cd)

{

       int i;

       int error = 0;

 

       if (cd->groups) {

              for (i = 0; cd->groups[i]; i++) {

                     error = sysfs_create_group(&cd->kobj, cd->groups[i]);

                     if (error) {      //创建文件夹错误

                            while (--i >= 0)      sysfs_remove_group(&cd->kobj, cd->groups[i]);

                            goto out;

                     }

              }

       }

out:

       return error;

}

 

//类设备删除组属性

static void class_device_remove_groups(struct class_device * cd)

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//打印类设备的主次设备号到buf中

static ssize_t   show_dev(struct class_device *class_dev, char *buf)

 

//设置class_devt_attr的属性(name, flag, show, store)

static struct class_device_attribute        class_devt_attr =

       __ATTR(dev, S_IRUGO, show_dev, NULL);

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//store操作,执行类设备uevnet函数的ADD操作

static ssize_t   store_uevent(

       struct class_device        *class_dev,

       const char                    *buf,

       size_t                          count)

{

       kobject_uevent(&class_dev->kobj,      KOBJ_ADD);

       return count;

}

 

//设置class_uevent_attr属性

static struct class_device_attribute        class_uevent_attr =

       __ATTR(uevent, S_IWUSR, NULL, store_uevent);

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类设备的初始化,具体操作如下:

//1、将类设备的kset挂到class_obj_subsys子系统下

//2、类设备kobj初始化

//3、挂空类设备的节点

void       class_device_initialize(struct class_device    *class_dev)

{

       //类设备的父节点为class_obj_subsys

       kobj_set_kset_s(class_dev, class_obj_subsys);

       kobject_init(&class_dev->kobj);

       INIT_LIST_HEAD(&class_dev->node);

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类设备的添加,具体操作如下:

//1、获取类设备,检查其合法性。

//2、设置类的kobj名字,设置其父设备,创建属性文件

//3、kobject_uevent(&class_dev->kobj, KOBJ_ADD);

//4、将类设备节点class_dev->node加到父类链表parent_class->children中

//5、调用父类所有接口的add函数,添加该类设备

int class_device_add(struct class_device *class_dev)

{

       struct class                   *parent_class = NULL;

       struct class_device        *parent_class_dev = NULL;

       struct class_interface     *class_intf;

       int error = -EINVAL;

 

       //获取类设备

       class_dev = class_device_get(class_dev);

       if (!class_dev)        return -EINVAL;

 

       //类设备ID没设置,退出

       if (!strlen(class_dev->class_id))    goto out1;

 

       //父类

       parent_class = class_get(class_dev->class);

       if (!parent_class)    goto out1;

 

       //父类设备

       parent_class_dev = class_device_get(class_dev->parent);

 

       /* first, register with generic layer. */

       //设置类设备的名字

       error = kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);

       if (error)        goto out2;

 

       //父类设备存在,kobj的父设备为父类设备,否则是子系统

       if (parent_class_dev)      class_dev->kobj.parent = &parent_class_dev->kobj;

       else                              class_dev->kobj.parent = &parent_class->subsys.kobj;

 

       //添加kobj到父设备链表中

       error = kobject_add(&class_dev->kobj);

       if (error)        goto out2;

 

       //在子系统文件夹中创建本设备属性link

       error = sysfs_create_link(&class_dev->kobj,         &parent_class->subsys.kobj, "subsystem");

       if (error)        goto out3;

       //创建类设备uevent属性文件

       error = class_device_create_file(class_dev, &class_uevent_attr);

       if (error)        goto out3;

 

       //类设备的主设备号存在,创建devt属性文件

       if (MAJOR(class_dev->devt)) {

              error = class_device_create_file(class_dev, &class_devt_attr);

              if (error) goto out4;

       }

 

       //添加类设备属性组

       error = class_device_add_attrs(class_dev);

       if (error)        goto out5;

 

       //有指定类设备的设备,创建设备link

       if (class_dev->dev) {

              error = sysfs_create_link(&class_dev->kobj,         &class_dev->dev->kobj, "device");

              if (error) goto out6;

       }

 

       //添加一个组

       error = class_device_add_groups(class_dev);

       if (error)        goto out7;

 

       //空函数

       error = make_deprecated_class_device_links(class_dev);

       if (error)        goto out8;

 

       //运行obj的uevent操作

       kobject_uevent(&class_dev->kobj, KOBJ_ADD);

 

       //将类设备节点加到父类链表中

       //调用父类所有接口的add函数,添加该类设备

       down(&parent_class->sem);

       list_add_tail(&class_dev->node,   &parent_class->children);

       list_for_each_entry(class_intf,      &parent_class->interfaces,    node) {

              if (class_intf->add)

                     class_intf->add(class_dev, class_intf);

       }

       up(&parent_class->sem);

 

       goto out1;

 

 out8:

       class_device_remove_groups(class_dev);

 out7:            //创建设备组失败

       if (class_dev->dev)

              sysfs_remove_link(&class_dev->kobj, "device");

 out6:            //创建设备link失败

       class_device_remove_attrs(class_dev);

 out5:            //添加类设备属性组失败

       if (MAJOR(class_dev->devt))

              class_device_remove_file(class_dev, &class_devt_attr);

 out4:            //设备devt属性文件创建失败

       class_device_remove_file(class_dev, &class_uevent_attr);

 out3:            //类设备uevent属性文件或在父类中的link文件创建失败

       kobject_del(&class_dev->kobj);

 out2:            //类设备名设置失败,添加kobj到父链表失败

       if(parent_class_dev)

              class_device_put(parent_class_dev);

       class_put(parent_class);

 out1:            //类设备ID没设置,类设备没有指定父类

       class_device_put(class_dev);

       return error;

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类设备的注册,实际就是调用类设备的初始化,然后add

int   class_device_register(struct class_device *class_dev)

{

       class_device_initialize(class_dev);

       return class_device_add(class_dev);

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类设备的创建,先根据参数新建并设置类设备,然后调用class_device_register进行注册

struct class_device        *class_device_create(

       struct class                   *cls,               //类设备所属的类(必有)

       struct class_device        *parent,          //类设备的父设备

       dev_t                           devt,                     //设备版本号

       struct device                 *device,         //关联的设备

       const char *fmt,    ...)                        //ID名

{

       va_list args;

       struct class_device        *class_dev = NULL;

       int retval = -ENODEV;

 

       //类未定义

       if (cls == NULL || IS_ERR(cls))          goto error;

 

       //申请一块内存,保存类设备(申请失败的代码,略)

       class_dev = kzalloc(sizeof(*class_dev), GFP_KERNEL);

      

       //设置类设备成员

       class_dev->devt = devt;                //设备版本号

       class_dev->dev = device;              //关联的设备

       class_dev->class = cls;                 //所属的类

       class_dev->parent = parent;          //父设备

       class_dev->release = class_device_create_release;

       class_dev->uevent = class_device_create_uevent;

 

       va_start(args, fmt);                      //格式化ID名

       vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);

       va_end(args);

 

       //类设备注册

       retval = class_device_register(class_dev);

       if (retval)              goto error;

 

       return class_dev;

 

error:

       kfree(class_dev);

       return ERR_PTR(retval);

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类设备的删除,应该是设备add操作的反操作

void       class_device_del(struct class_device *class_dev)

{

       //获取类设备所属的类和父设备

       struct class                   *parent_class = class_dev->class;

       struct class_device        *parent_device = class_dev->parent;

       struct class_interface     *class_intf;

 

       //如果所属的类存在(实际也不可能不存在)

       if (parent_class) {

              down(&parent_class->sem);

              list_del_init(&class_dev->node);          //删除类设备节点,并初始化

              //父类接口都运行一次remove函数来删除指定节点

              list_for_each_entry(class_intf, &parent_class->interfaces, node)

                     if (class_intf->remove)

                            class_intf->remove(class_dev, class_intf);

              up(&parent_class->sem);

       }

 

       //类设备关联的设备存在,删除link

       if (class_dev->dev) {

              remove_deprecated_class_device_links(class_dev);      //空函数

              sysfs_remove_link(&class_dev->kobj, "device");

       }

 

       //删除设备的link和属性文件

       sysfs_remove_link(&class_dev->kobj, "subsystem");

       class_device_remove_file(class_dev, &class_uevent_attr);

       if (MAJOR(class_dev->devt))

              class_device_remove_file(class_dev, &class_devt_attr);

       class_device_remove_attrs(class_dev);

       class_device_remove_groups(class_dev);

 

       kobject_uevent(&class_dev->kobj, KOBJ_REMOVE);

       kobject_del(&class_dev->kobj);

 

       class_device_put(parent_device);

       class_put(parent_class);

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类设备的反注册,直接调用上面的函数

void       class_device_unregister(struct class_device *class_dev)

{

       class_device_del(class_dev);

       class_device_put(class_dev);

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类设备销毁,具体操作是根据指定的设备号从cls的类设备链表中找到类设备,然后运行反注册函数

void       class_device_destroy(struct class *cls, dev_t devt)

{

       struct class_device *class_dev = NULL;

       struct class_device *class_dev_tmp;

 

       //根据设备号从cls的类设备链表中找到指定的类设备

       down(&cls->sem);

       list_for_each_entry(class_dev_tmp, &cls->children, node) {

              if (class_dev_tmp->devt == devt) {

                     class_dev = class_dev_tmp;

                     break;

              }

       }

       up(&cls->sem);

 

       //类设备反注册

       if (class_dev)         class_device_unregister(class_dev);

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类设备的引用和释放

struct class_device * class_device_get(struct class_device *class_dev)

{

       if (class_dev)         return     to_class_dev(kobject_get(&class_dev->kobj));

       return NULL;

}

 

void class_device_put(struct class_device *class_dev)

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类接口操作,具体操作是将接口的节点挂到所属类的接口链表中,然后遍历类的类设备链表和设备链表,分别调用add和add_device函数

int   class_interface_register(struct class_interface      *class_intf)

{

       struct class *parent;

       struct class_device *class_dev;

       struct device *dev;

 

       //类接口不存在,或类接口所属类不存在

       if (!class_intf || !class_intf->class) return -ENODEV;

       parent = class_get(class_intf->class);

       if (!parent)     return -EINVAL;

 

       down(&parent->sem);

       //添加当前接口节点到父节点中,

       //遍历类的类设备链表,执行新挂接口的add函数

       list_add_tail(&class_intf->node, &parent->interfaces);

       if (class_intf->add) {

              list_for_each_entry(class_dev, &parent->children, node)

                     class_intf->add(class_dev, class_intf);

       }

       //遍历类的类设备链表,执行新挂接口的add函数

       if (class_intf->add_dev) {

              list_for_each_entry(dev, &parent->devices, node)

                     class_intf->add_dev(dev, class_intf);

       }

       up(&parent->sem);

 

       return 0;

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类接口的卸载,操作是分别调用remove和remove_dev函数

void       class_interface_unregister(struct class_interface *class_intf)

{

       struct class                   * parent = class_intf->class;

       struct class_device        *class_dev;

       struct device                 *dev;

 

       //父类不存在,错误

       if (!parent)     return;

 

       down(&parent->sem);

       list_del_init(&class_intf->node);

       if (class_intf->remove) {

              list_for_each_entry(class_dev, &parent->children, node)

                     class_intf->remove(class_dev, class_intf);

       }

       if (class_intf->remove_dev) {

              list_for_each_entry(dev, &parent->devices, node)

                     class_intf->remove_dev(dev, class_intf);

       }

       up(&parent->sem);

 

       class_put(parent);

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//类的初始化

int   __init     classes_init(void)

{

       int retval;

 

       //类子系统注册

       retval = subsystem_register(&class_subsys);

       if (retval)              return retval;

 

       //初始化类设备obj的set

       kset_init(&class_obj_subsys);

       //设置类设备子系统的父obj为类设备子系统

       if (!class_obj_subsys.kobj.parent)

              class_obj_subsys.kobj.parent = &class_obj_subsys.kobj;

       return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值