device 注册的时候 可以在device里加入自定义的attribute,这样在device注册到 sysfs的时候 可以生成对应该的attribute file.我们可以利用自定义的attribute 节点来做一些自定义的功能 。比如:一些debug 功能 。
attribute以两层的结构被挂在device之下,如下图:
在sysfs里对应该的结构会是这样的:
要在自己的code里加入自定义 的attribute, 需要 以下这几步:
- attribute define
- attributes array define
- attribute group define
- attribute group array define
- add attribute group array define in device define
- registe device
- attribute define
attribute 定义根据不同的device是有所不同。device/bus都有各自的attribute的定义 。他们都是对原始attribute结构的扩展。原始的attribute只定义 了基本的name & mode ,
name是attribute的名字,可是最终生成文件节点的名称。
mode是文件节点的访问权限
struct attribute {
const char *name;
umode_t mode;
};
原始节点并不能提供了任何功能 。根据不同的设备类型需要不同的设备对他进行了扩展,常见的有下面几种:
- device_attribute
- driver_attribute
- class_attribute
- bus_attribute
在本节的内容中不分开细说每种attribute,后面再在别的小节里详细介绍他们各自要怎么定义 。在本节中我们把重点放在attribute是如何添加进系统的,因为虽然有各种attribute.但他们的注册流程 是一样的,不同的只是他们的定义 有所差别。
2. attributes array define
在上一节定义 了多个attribute后。我们需要 把这些attribute 组织成一个NULL 结束的 attribute 指针数组
struct attribute * attr_0_attrs[] = {
&attr_0_0,
&attr_0_1,
&attr_0_2
NULL,
}
- attribute group define
把上一节打包好的attribute数组放进attribute group里面
struct attribute_group {
const char *name;
umode_t (*is_visible)(struct kobject *,
struct attribute *, int);
umode_t (*is_bin_visible)(struct kobject *,
struct bin_attribute *, int);
struct attribute **attrs;
struct bin_attribute **bin_attrs;
};
- attribute group array define
在上一节定义 了多个attribute group后。我们需要 把这些attribute group组织成一个NULL 结束的 attribute group指针数组
struct attribute_group * attr_group[] = {
&attr_group_0,
&attr_group_1,
NULL,
}
- add attribute group array define in device define
把上一节打包好的attribute group数组放进device里面
struct device {
.....
const struct attribute_group **groups; /* optional groups */
.....
};
- registe device
int device_register(struct device *dev)
第5-6小节要根据自己定义的device有所差别,
以下是实作例子:
//0. device attr function define
static ssize_t debug1_store(struct device * dev, struct device_attribute *attr, const char *buf, size_t count)
{
printk("%s_%d @@@@####(%s)\n", func, LINE, buf);
return count;
}
static ssize_t debug1_show(struct device *dev, struct device_attribute *attr, char *buf)
{
printk("%s_%d @@@@####\n", func, LINE);
return 0;
}
static ssize_t debug2_store(struct device * dev, struct device_attribute *attr, const char *buf, size_t count)
{
printk("%s_%d @@@@####(%s)\n", func, LINE, buf);
return count;
}
static ssize_t debug2_show(struct device *dev, struct device_attribute *attr, char *buf)
{
printk("%s_%d @@@@####\n", func, LINE);
return 0;
}
//1.attr define
//1.attr define
DEVICE_ATTR_RW(debug1);
DEVICE_ATTR_RW(debug2);
//2.attr array define
struct attribute * rdvbDebug_attrs[] = {
(struct attribute *)&dev_attr_debug1,
(struct attribute *)&dev_attr_debug2,
NULL,
};
//3. attr group define
// unnamed attribute group : ATTRIBUTR_GROUPS(name)
“…/media/platform/rtk-tv/rtk_tv_dev.c” 74L, 1883C 7,2-9 Top
}
static ssize_t debug2_show(struct device *dev, struct device_attribute *attr, char *buf)
{
printk("%s%d @@@@####\n", func, LINE);
return 0;
}
//1.attr define
//1.attr define
DEVICE_ATTR_RW(debug1);
DEVICE_ATTR_RW(debug2);
//2.attr array define
struct attribute * rdvbDebug_attrs[] = {
(struct attribute *)&dev_attr_debug1,
(struct attribute *)&dev_attr_debug2,
NULL,
};
//3. attr group define
// unnamed attribute group : ATTRIBUTR_GROUPS(_name)
static const struct attribute_group rdvbDebug_group = {
.name = “rdvbDebug”,
.attrs = rdvbDebug_attrs,
};
//4 attr group define
__ATTRIBUTE_GROUPS(rdvbDebug);
//======================================================================
struct platform_device rdvb_dev = {
.name = “rdvb”,
.id = -1,
.dev = {
.groups = &rdvbDebug_groups,
},
.num_resources = 0,
};