小结:
这个文件中,声明了类子系统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;
}