22081-1-4 驱动--获取设备树节点属性

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");

猜你喜欢

转载自blog.csdn.net/wyl2333/article/details/128553031