在led驱动框架:led-class.c源码分析中已经对led框架源码进行了分析,本文章将介绍如何简单使用led框架。
led框架向驱动开发者暴露的接口如下
int led_classdev_register(struct device *parent, struct led_classdev *led_cdev);
void led_classdev_unregister(struct led_classdev *led_cdev);
所以,在我们编写驱动模块时,需要在初始化函数中注册led_classdev实体,在退出函数中注销它。下列代码是led框架最简单的使用流程:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/leds.h>
static void my_brightness_set(struct led_classdev *led_cdev, enum led_brightness value)
{
//具体的硬件操作逻辑,根据传入的value设置led相应gpio
}
//创建并填充led_classdev实体
static struct led_classdev my_led_classdev=
{
.name = "my_led",
.brightness = 0,
.brightness_set = my_brightness_set,
};
//模块初始化函数
static int __init led_init(void)
{
int ret = -1;
//注册led_classdev实体
ret = led_classdev_register(NULL, &my_led_classdev);
if(ret < 0)
{
//错误处理
}
return 0;
}
//模块退出函数
static void __exit led_exit(void)
{
//注销led_classdev实体
led_classdev_unregister(&my_led_classdev);
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("poetrycoding <3101152122@qq.com>");
MODULE_DESCRIPTION("test");
这里有几个注意点:
led_classdev实体需要与驱动的生命周期相同,因为需要保证驱动框架能够长期使用它。所以,可以向上述代码一样,将其定义为全局变量,当然也可以将其放到堆空间,模块退出时手动释放空间。
上述代码编译成模块(或者直接编译进内核),装载到系统中后,sysfs中就会暴露出相应的接口;具体表现为/sys/class下会增加一个leds的文件夹,文件夹下有名为my_led的文件夹,里边是一些attribute文件。
上述代码是led驱动框架最简单的使用情况,真实环境下的代码肯定不会这么写,但大体思路相同,无非是增加更多的细节和特性,比如结合总线模型来书写等。