linux驱动:利用of_函数读取设备树结点/属性信息(含错误处理)

实验说明:
目的:期望通过linux/of.h中相关函数,在驱动中读取设备树相关结点信息和属性信息
要求:①读取设备树/backlight结点下的属性,以及属性信息,合理处理返回值和错误信息
②设计一个能够读取u32类型属性的通用函数,并在init函数中输出信息

驱动程序:

/** 此文件为linux 内核 of函数测试文件
 *  实验目的:在init函数中使用of函数读取设备树中的 根节点下xxx设备节点信息
 *  其路径为: /backlight
 *  内容为:backlight {
		compatible = "pwm-backlight";
		pwms = <&pwm1 0 5000000>;
		brightness-levels = <0 4 8 16 32 64 128 255>;
		default-brightness-level = <6>;
		status = "okay";
	};
 */

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

struct device_node* ofdts_node;
struct property*    blprop;
int ret = 0;
const char* out_string;
int result = 0;
int mem_count = 0;
u32* out_values;
static u32 show_members(int mem_count, char* prop_name)
{
    u8 i;
    
    if(mem_count < 0){
        printk("fail_property_count_elems_of_size!!!\n");
        return -ENODEV;
    }
    else if (mem_count == 0)
    {   
        printk("%s中有%d个元素\n",prop_name, mem_count);
    }else if(mem_count == 1){
        printk("%s中有%d个元素\n",prop_name, mem_count);
        out_values = kmalloc(sizeof(u32) * mem_count,GFP_KERNEL);
        if(!out_values){
            printk("fail_mem\n");
            return -ENODEV;
        }
        ret = of_property_read_u32(ofdts_node, prop_name, out_values);
        if(ret < 0){
            printk("fail_read_u32!!!\n");
            kfree(out_values);
            return -ENODEV;
        }
        printk("%s中的元素为:%d\n",prop_name, *out_values);  
    }
    else{
        printk("%s中有%d个元素\n",prop_name, mem_count);
        out_values = kmalloc(sizeof(u32) * mem_count,GFP_KERNEL);
        ret = of_property_read_u32_array(ofdts_node, prop_name, out_values,mem_count);
        if(ret < 0){
            printk("fail_read_u32_array!!!\n");
            kfree(out_values);
            return -ENODEV;
        }
        printk("%s中有元素为:",prop_name); 
        for(i = 0; i < mem_count; i++){
            printk("%d\t",out_values[i]); 
        }
    }
    return 0;
}

static int __init ofdts_init(void)
{
    printk("\nofdts_initing.........\n");
/* 0. 提取 backlight 节点*/
    ofdts_node = of_find_node_by_name(NULL, "backlight");
    if(!ofdts_node){
        goto fail_node;
    }else{
        printk("0. 获取节点:%s 成功~\n", ofdts_node->name);
    }

/* 1. 获取compatible = "pwm-backlight"  和 status = "okay"这俩都是字符串类型的,使用两个不同的函数分别测试*/
    // 1 compatible
    ret = of_property_read_string(ofdts_node, "compatible", &out_string);
    if(ret < 0){
        goto fail_property_read_string;
    }else{
        printk("1.0 获取compatible成功:%s\n", out_string);
    }
    // 2 status
    blprop = of_find_property(ofdts_node, "status", NULL);
    if(!blprop){
        goto fail_find_property;
    }else{
        printk("1.1 获取status成功:%s\n", (char*)blprop->value);
    }

/* 2. 获取default-brightness-level = <6>; */
    mem_count = of_property_count_elems_of_size(ofdts_node, "default-brightness-level", sizeof(u32));
    result = show_members(mem_count, "default-brightness-level");
	if(result < 0){
        return result;
    }
/* 3. brightness-levels = <0 4 8 16 32 64 128 255>; */
    mem_count = of_property_count_elems_of_size(ofdts_node, "brightness-levels", sizeof(u32));
    result = show_members(mem_count, "brightness-levels");
	
    printk("ofdts_init.........OK!!!\n");   
    return result;

fail_find_property:
fail_property_read_string:
    printk("fail_property_read_string!!!\n");
    return -ENODEV;
fail_node:
    printk("fail_find_node_byname!!!\n");
    return -ENODEV;
}


static void __exit ofdts_exit(void)
{
    kfree(out_values);
    printk("ofdts_exit.........OK!!!\n");
}



/** 注册函数 */
module_init(ofdts_init);
module_exit(ofdts_exit);

/** license和作者*/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("QJY");

注意:程序能够测试通过,可能返回值处理以及错误处理有不合理之处,作者并未排查,本程序仅作为练习测试使用;

测试结果:
linux驱动:利用of_函数读取设备树结点/属性信息(含错误处理)_第1张图片

你可能感兴趣的:(linux驱动相关)