实验说明:
目的:期望通过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 <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_device.h>
#include <linux/slab.h>
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");
注意:程序能够测试通过,可能返回值处理以及错误处理有不合理之处,作者并未排查,本程序仅作为练习测试使用;
测试结果: