1、设备树节点结构体
struct device_node {
const char *name; //节点名 mynode
const char *full_name;//节点全名mynode@0x12345678
struct property *properties;//设备树节点属性链表头节点地址指针
struct device_node *parent;//当前节点父节点地址
struct device_node *child;//当前节点子节点地址
struct device_node *sibling;//兄弟节点地址
};
2、设备树节点的属性(键值对)结构体
struct property {
char *name;//键名
int length;//值的长度
void *value;//值
struct property *next;//指向下一个属性节点的指针
};
3、获取设备树节点的API(3种方式)
头文件:#include<linux/of.h>
(1)struct device_node *of_find_node_by_path(const char *path)
功能:通过路径获取设备树节点信息
path:设备树节点路径 ("/mynode@0x12345678")
返回值:成功返回目标节点首地址,失败返回NULL
(2)struct device_node *of_find_node_by_name(struct device_node *from,
const char *name);
功能:通过节点名获取设备树节点信息
参数:
from:已知的节点首地址,(NULL,默认从根节点开始解析)
name:节点名字:"mynode"
返回值:成功返回目标节点首地址,失败返回NULL
(3)struct device_node *of_find_compatible_node(struct device_node *from,
const char *type, const char *compat);
功能:通过节点中的conpatible来解析获取设备树节点信息
参数
from:已知的节点首地址,(NULL,默认从根节点开始解析)
type:填NULL
compat:compatible的值
返回值:成功返回目标节点首地址,失败返回NULL
实例:通过获取设备树的节点指针,访问成员(属性),再访问属性相关信息
#include<linux/init.h>
#include<linux/module.h>
#include<linux/of.h>
struct device_node* node;
static int __init mycdev_init(void)
{
node=of_find_node_by_path("/mynode@0x12345678");
if(node==NULL)
{
printk("通过路径获取设备树节点信息失败\n");
return -ENODATA;
}
printk("通过路径解析设备树节点信息成功\n");
printk("name=%s,value=%s\n",node->properties->name,(char *)node->properties->value);
printk("name=%s,value=%s\n",node->properties->next->name,(char *)node->properties->next->value);
printk("name=%s,value=%#x %#x\n",node->properties->next->next->name,__be32_to_cpup(node->properties->next->next->value),__be32_to_cpup(node->properties->next->next->value+4));
return 0;
}
static void __exit mycdev_exit(void)
{
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
4、通过节点信息结构体指针和键名获取属性的API
struct property *of_find_property(const struct device_node *np,
const char *name,
int *lenp)
功能:
通过节点信息结构体和键名获取指定属性信息
参数:
np:节点结构体指针
name:键名
lenp:获取到属性值的长度指针
返回值:成功返回目标属性结构体指针,失败返回NULL
实例:通过返回的属性结构体指针访问属性相关信息
#include<linux/init.h>
#include<linux/module.h>
#include<linux/of.h>
struct device_node* node;
struct property* pr;
static int __init mycdev_init(void)
{
int len,i;
node=of_find_node_by_path("/mynode@0x12345678");
if(node==NULL)
{
printk("通过路径获取设备树节点信息失败\n");
return -ENODATA;
}
printk("通过路径获取设备树节点信息成功\n");
pr=of_find_property(node,"astring",&len);
if(pr==NULL)
{
printk("获取属性失败\n");
return -ENODATA;
}
printk("name=%s,value=%s",pr->name,(char *)pr->value);
pr=of_find_property(node,"binary",&len);
if(pr==NULL)
{
printk("获取属性失败\n");
return -ENODATA;
}
for(i=0;i<len;i++)
{
printk("name=%s,value=%#x\n",pr->name,*((char *)pr->value+i));
}
return 0;
}
static void __exit mycdev_exit(void)
{
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
5、通过节点信息结构体指针和键名获取的属性值存放到变量或数组的API
1.int of_property_read_u32_index(const struct device_node *np,
const char *propname, u32 index, u32 *out_value)
功能:获取u32类型的值
参数:
np:设备树节点结构体指针
proname:键名
index:索引号,第一个数值索引号为0,依次+1
out_value:获取到的值存放的空间首地址
返回值:成功返回0,失败返回错误码
2.int of_property_read_variable_u32_array(const struct device_node *np,
const char *propname,
u32 *out_values,
size_t sz_min,
size_t sz_max)
功能:将获取到的u32类型的值存放在array数组中
参数:
np:设备树节点结构体指针
proname:键名
out_value:获取到的值存放的空间首地址(数组名)
min:期待读取到的值的最小数量
max:期待读取到的值的最大数量
返回值:成功返回获取数组元素的个数,失败返回错误码
3.int of_property_read_string(const struct device_node *np,
const char *propname,
const char **out_string)
功能:获取字符串类型的值
参数:
np:设备树节点结构体指针
proname:键名
out_string:获取到的字符串类型的值的首地址
返回值:成功返回0,失败返回错误码
4.int of_property_read_variable_u8_array(const struct device_node *np,
const char *propname, u8 *out_values,
size_t sz_min, size_t sz_max)
功能:读取u8类型的数组
参数:
np:设备树节点结构体指针
proname:键名
out_value:获取到的值存放的空间首地址(数组名)
min:期待读取到的值的最小数量
max:期待读取到的值的最大数量
返回值:成功返回获取数组元素的个数,失败返回错误码
5.int of_property_read_u8_array(const struct device_node *np,
const char *propname,
u8 *out_values, size_t sz)
功能:读取u8类型的数组
参数:
np:设备树节点结构体指针
proname:键名
out_value:获取到的值存放的空间首地址(数组名)
sz:数组成员的个数
返回值:成功返回0,失败返回错误码
实例:
#include<linux/init.h>
#include<linux/module.h>
#include<linux/of.h>
struct device_node* node;
unsigned int val;
unsigned int array[2]={0};
const char *string;
unsigned char num[6];
int ret,i;
static int __init mycdev_init(void)
{
node=of_find_node_by_path("/mynode@0x12345678");
if(node==NULL)
{
printk("通过路径获取设备树节点信息失败\n");
return -ENODATA;
}
printk("通过路径获取设备树节点信息成功\n");
//获取u32类型的值(一个一个的获取数值)
if(of_property_read_u32_index(node,"unit",0,&val))
{
printk("获取u32类型的值失败\n");
return -ENODATA;
}
printk("%#x\n",val);
if(of_property_read_u32_index(node,"unit",1,&val))
{
printk("获取u32类型的值失败\n");
return -ENODATA;
}
printk("%#x\n",val);
//获取u32类型的值存放到arry数组中
ret=of_property_read_variable_u32_array(node,"unit",array,2,2);
if(ret<0)
{
printk("获取u32类型的值存入数组失败\n");
return -ENODATA;
}
for(i=0;i<ret;i++)
{
printk("%#x\n",array[i]);
}
//获取字符串类型的值
if(of_property_read_string(node,"astring",&string))
{
printk("获取字符串类型的值失败\n");
return -ENODATA;
}
printk("%s\n",string);
//读取u8类型的数组
ret=of_property_read_variable_u8_array(node,"binary",num,6,6);
if(ret<0)
{
printk("读取u8类型的值存入数组失败\n");
return -ENODATA;
}
for(i=0;i<ret;i++)
{
printk("%#x\n",num[i]);
}
/*
if(of_property_read_u8_array(node,"binary",num,6))
{
printk("读取u8类型的值存入数组失败\n");
return -ENODATA;
}
printk("%#x %#x %#x %#x %#x %#x\n",num[0],num[1],num[2],num[3],num[4],num[5]);
*/
return 0;
}
static void __exit mycdev_exit(void)
{
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");