led子系统之实战篇(实际led驱动编写)

来源:互联网 发布:怎么取消差评淘宝 编辑:程序博客网 时间:2024/05/21 17:20

led驱动应该是linux驱动中是最简单的一个,下面实际讲解关于led驱动编写的过程。

早期的led驱动实际上在/dev/led生成文件,当led成为一个单独的子系统时,我们要用到led的子系统以及相关的函数

#include <linux/kernel.h>#include <linux/init.h>#include <linux/platform_device.h>#include <linux/leds.h>#include <linux/gpio.h>#include <linux/slab.h>#include <linux/module.h>#include <linux/spmi.h>头文件不说了
static struct led_classdevled_cdev;             //直接定义led_classdev的变量
<pre name="code" class="cpp">static void carl_wang_led_set(struct led_classdev *led_cdev,    enum led_brightness value){led_cdevbrightness = value;                               //赋值操作,当对led的文件写时会调用这个函数,剩余的操作和平台相关</span>}static enum led_brightness carl_wang_led_get(struct led_classdev * led_dev){return led_cdev.brightness; //读取操作,当cat时会调用}static int carl_wang_led_probe(struct spmi_device *dev ){int ret;led_cdev.brightness_set = carl_wang_led_set; //函数指针赋值led_cdev.brightness_get = carl_wang_led_get;led_cdev.name = "carl_wang_led"; //在sys/class/leds/ 生成carl_wang_led的目录/* register our new led device */ret = led_classdev_register(&dev->dev, &led_cdev); //led class 的注册if (ret < 0) {dev_err(&dev->dev, "led_classdev_register failed\n");return ret;}return 0;}static int carl_wang_led_remove(struct spmi_device * dev){led_classdev_unregister(&led_cdev);return 0;}#ifdef CONFIG_OFstatic struct of_device_id spmi_match_table[] = {{ .compatible = "qcom,leds-qpnp",},{ },};#else#define spmi_match_table NULL#endifstatic struct spmi_driver carl_wang_led_driver = {.probe = carl_wang_led_probe, //device和device_driver匹配到后调用的函数.remove = carl_wang_led_remove, .driver = { .name = "qcom,leds-qpnp", //spmi总线上一定要有与之对应的相同name(名字)的device.owner = THIS_MODULE,.of_match_table = spmi_match_table, //和name的作用一样,用于匹配device和device_driver的凭证},};static int __init qpnp_led_init(void){return spmi_driver_register(&carl_wang_led_driver); //高通平台专有的spmi的总线注册驱动的函数}module_init(qpnp_led_init);static void __exit qpnp_led_exit(void){spmi_driver_unregister(&carl_wang_led_driver);}module_exit(qpnp_led_exit);MODULE_AUTHOR("carl_wang@unicair");MODULE_DESCRIPTION("carl_wang LED driver");MODULE_LICENSE("GPL");



每个平台上的注册函数都是不一样的,但是实际上我们的目的嗾使一样的,那就是使用户空间的能够访问到这些device,其实关键有几步需要注意

1. 定义dirver,比如我们是spmi总线上的,一般有spmi_driver,有的平台是挂在paltform总线上的,就是使用platform_driver定义的,并且对内部的元素进行填充或者是初始化;

2.调用总线驱动注册函数,当总线上已经存在相同的name(一般)device已经挂载上,那么当driver注册的时候会遍历所有总线上的device,当找到相同的时,这个相同取决于总线的match函数,一般比较的是name,相同时返回1,然后调用驱动中的probe函数

3.在probe函数中,我们要针对led_classdev 的变量进行初始化,一般初始化的的brightness_set,brightness_get,name,其中name是实际生成的leds下的子目录的名字。

4.调用led_classdev_register(struct device *parent, struct led_classdev *led_cdev)函数,则大功告成。

当然了1,2步骤可以不用的,我们完全可以将led_classdev_register函数的调用放在其他的比如lcd背光的probe函数中,或者是按键的probe函数中,我们要的只是在用户空间能生成对应的访问接口。


可以看到在class/leds下有calr_wang_led的目录,我们仅仅需要访问的是brightness,输入echo 255 > brightness 然后cat brightness ,看看是不是255。

0 0