本文转载自:http://blog.csdn.net/eastmoon502136/article/details/37606487

巴西世界杯,德国7比1东道主,那个惨不忍睹啊,早上起来看新闻,第一眼看到7:1还以为点球也能踢成这样,后来想想,点球对多嘛6比1啊,接着就是各种新闻铺天盖地的来了。其实失败并没有什么,人生若是能够成功一次,那么再多的失败也是值得的,脚踏实地,失败了再次爬起来。很多时候,在一切都那么顺利的情况下,反而觉得没有啥意思,有一些挑战,一些失败,一些打击,接着,就会很努力很努力地去做,慢慢地就会被自己征服,很喜欢这种感受,废话说多了,还是接着研究led子系统吧。

对于led子系统中,有那么多得trigger,下面就来简单了解下。

1、default-on

  1. <pre name="code" class="html">static voiddefon_trig_activate(struct led_classdev *led_cdev)
  2. {
  3. led_set_brightness(led_cdev,led_cdev->max_brightness);
  4. }
  5. static structled_trigger defon_led_trigger = {
  6. .name     = "default-on",
  7. .activate = defon_trig_activate,
  8. };
  9. static voiddefon_trig_activate(struct led_classdev *led_cdev)
  10. {
  11. led_set_brightness(led_cdev,led_cdev->max_brightness);
  12. }
  13. static structled_trigger defon_led_trigger = {
  14. .name     = "default-on",
  15. .activate = defon_trig_activate,
  16. };

Default-on主要是设置led为最大亮度。

2、backlight

  1. struct bl_trig_notifier {
  2. structled_classdev *led;       //led子系统设备
  3. intbrightness;               //亮度
  4. intold_status;
  5. structnotifier_block notifier;    //内核通知链
  6. unsignedinvert;
  7. };
  8. static struct led_trigger bl_led_trigger ={
  9. .name                = "backlight",
  10. .activate  = bl_trig_activate,
  11. .deactivate       = bl_trig_deactivate
  12. };
  13. static void bl_trig_activate(structled_classdev *led)
  14. {
  15. intret;
  16. structbl_trig_notifier *n;
  17. n= kzalloc(sizeof(struct bl_trig_notifier), GFP_KERNEL);
  18. led->trigger_data= n;
  19. if(!n) {
  20. dev_err(led->dev,"unable to allocate backlight trigger\n");
  21. return;
  22. }
  23. ret= device_create_file(led->dev, &dev_attr_inverted);
  24. if(ret)
  25. gotoerr_invert;
  26. n->led= led;
  27. n->brightness= led->brightness;
  28. n->old_status= UNBLANK;
  29. n->notifier.notifier_call= fb_notifier_callback;
  30. ret= fb_register_client(&n->notifier);
  31. if(ret)
  32. dev_err(led->dev,"unable to register backlight trigger\n");
  33. return;
  34. err_invert:
  35. led->trigger_data= NULL;
  36. kfree(n);
  37. }

其中fb_register_client注册到了framebuffer中的fb_notifier_list中,一旦framebuffer驱动中有事件,就会调用内核通知链中注册好的函数fb_notifier_callback。

关于内核通知链,这里就插播一曲来自网络的摘抄了:

大多数内核子系统都是相互独立的,因此某个子系统可能对其它子系统产生的事件感兴趣。为了满足这个需求,也即是让某个子系统在发生某个事件时通知其它的子系统,Linux内核提供了通知链的机制。通知链表只能够在内核的子系统之间使用,而不能够在内核与用户空间之间进行事件的通知。

通知链表是一个函数链表,链表上的每一个节点都注册了一个函数。当某个事情发生时,链表上所有节点对应的函数就会被执行。所以对于通知链表来说有一个通知方与一个接收方。在通知这个事件时所运行的函数由被通知方决定,实际上也即是被通知方注册了某个函数,在发生某个事件时这些函数就得到执行。其实和系统调用signal的思想差不多。

通知链技术可以概括为:事件的被通知者将事件发生时应该执行的操作通过函数指针方式保存在链表(通知链)中,然后当事件发生时通知者依次执行链表中每一个元素的回调函数完成通知。

  1. static int fb_notifier_callback(struct notifier_block *p,
  2. unsignedlong event, void *data)
  3. {
  4. structbl_trig_notifier *n = container_of(p,
  5. structbl_trig_notifier, notifier);
  6. struct led_classdev*led = n->led;
  7. struct fb_event*fb_event = data;
  8. int *blank =fb_event->data;
  9. int new_status =*blank ? BLANK : UNBLANK;
  10. switch (event) {
  11. case FB_EVENT_BLANK :
  12. if(new_status == n->old_status)
  13. break;
  14. if((n->old_status == UNBLANK) ^ n->invert) {
  15. n->brightness= led->brightness;
  16. led_set_brightness(led,LED_OFF);
  17. } else {
  18. led_set_brightness(led,n->brightness);
  19. }
  20. n->old_status= new_status;
  21. break;
  22. }
  23. return 0;
  24. }

如果触发了FB_EVENT_BLANK,那么就执行相应的操作。

3、timer

  1. static structled_trigger timer_led_trigger = {
  2. .name     = "timer",
  3. .activate =timer_trig_activate,
  4. .deactivate =timer_trig_deactivate,
  5. };
  6. static voidtimer_trig_activate(struct led_classdev *led_cdev)
  7. {
  8. int rc;
  9. led_cdev->trigger_data= NULL;
  10. rc =device_create_file(led_cdev->dev, &dev_attr_delay_on);
  11. if (rc)
  12. return;
  13. rc =device_create_file(led_cdev->dev, &dev_attr_delay_off);
  14. if (rc)
  15. gotoerr_out_delayon;
  16. led_blink_set(led_cdev,&led_cdev->blink_delay_on,
  17. &led_cdev->blink_delay_off);
  18. led_cdev->trigger_data= (void *)1;
  19. return;
  20. err_out_delayon:
  21. device_remove_file(led_cdev->dev,&dev_attr_delay_on);
  22. }

当某个led_classdev与之连接后,这个触发器会在/sys/class/leds/<device>/下创建两个文件delay_on和delay_off。用户空间往这两个文件中写入数据后,相应的led会按照设置的高低电平的时间(ms)来闪烁。如果led_classdev注册了硬件闪烁的接口led_cdev->blink_set就是用硬件控制闪烁,否则用软件定时器来控制闪烁。

4、heatbeat

  1. static structled_trigger heartbeat_led_trigger = {
  2. .name     = "heartbeat",
  3. .activate =heartbeat_trig_activate,
  4. .deactivate = heartbeat_trig_deactivate,
  5. };
  6. structheartbeat_trig_data {
  7. unsigned int phase;
  8. unsigned int period;
  9. struct timer_listtimer;
  10. };
  11. static voidheartbeat_trig_activate(struct led_classdev *led_cdev)
  12. {
  13. structheartbeat_trig_data *heartbeat_data;
  14. heartbeat_data =kzalloc(sizeof(*heartbeat_data), GFP_KERNEL);
  15. if (!heartbeat_data)
  16. return;
  17. led_cdev->trigger_data= heartbeat_data;
  18. setup_timer(&heartbeat_data->timer,
  19. led_heartbeat_function, (unsigned long)led_cdev);
  20. heartbeat_data->phase= 0;
  21. led_heartbeat_function(heartbeat_data->timer.data);
  22. }

设置了heartbeat_data->phase,然后调用led_heartbeat_function。

  1. static voidled_heartbeat_function(unsigned long data)
  2. {
  3. struct led_classdev*led_cdev = (struct led_classdev *) data;
  4. structheartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
  5. unsigned longbrightness = LED_OFF;
  6. unsigned long delay =0;
  7. /* acts like anactual heart beat -- ie thump-thump-pause... */
  8. switch(heartbeat_data->phase) {
  9. case 0:
  10. /*
  11. * The hyperbolic function below modifies the
  12. * heartbeat period length in dependency of the
  13. * current (1min) load. It goes through thepoints
  14. * f(0)=1260, f(1)=860, f(5)=510,f(inf)->300.
  15. */
  16. heartbeat_data->period= 300 +
  17. (6720<< FSHIFT) / (5 * avenrun[0] + (7 << FSHIFT));
  18. heartbeat_data->period=
  19. msecs_to_jiffies(heartbeat_data->period);
  20. delay =msecs_to_jiffies(70);
  21. heartbeat_data->phase++;
  22. brightness =led_cdev->max_brightness;
  23. break;
  24. case 1:
  25. delay =heartbeat_data->period / 4 - msecs_to_jiffies(70);
  26. heartbeat_data->phase++;
  27. break;
  28. case 2:
  29. delay =msecs_to_jiffies(70);
  30. heartbeat_data->phase++;
  31. brightness =led_cdev->max_brightness;
  32. break;
  33. default:
  34. delay =heartbeat_data->period - heartbeat_data->period / 4 -
  35. msecs_to_jiffies(70);
  36. heartbeat_data->phase= 0;
  37. break;
  38. }
  39. led_set_brightness(led_cdev,brightness);
  40. mod_timer(&heartbeat_data->timer,jiffies + delay);
  41. }

通过定时来实现类似于心跳的led灯。

5、ide-disk

  1. static voidledtrig_ide_timerfunc(unsigned long data)
  2. {
  3. if (ide_lastactivity!= ide_activity) {
  4. ide_lastactivity =ide_activity;
  5. /* INT_MAX will seteach LED to its maximum brightness */
  6. led_trigger_event(ledtrig_ide,INT_MAX);
  7. mod_timer(&ledtrig_ide_timer,jiffies + msecs_to_jiffies(10));
  8. } else {
  9. led_trigger_event(ledtrig_ide,LED_OFF);
  10. }
  11. }
  12. static int __initledtrig_ide_init(void)
  13. {
  14. led_trigger_register_simple("ide-disk",&ledtrig_ide);
  15. return 0;
  16. }

通过定时器实现类似于硬盘灯的指示。

以上便是led子系统中的trigger的一些简单介绍。

最新文章

  1. Linux CentOS6.x ip设置(网卡设置)
  2. Jquery学习笔记--性能优化建议
  3. [工作中的设计模式]备忘录模式memento
  4. 1. python中的随机函数
  5. Java多线程-线程的调度(合并)
  6. 为什么我刚发表的文章变成了“待审核”,csdn有没有官方解释啊
  7. [LeetCode OJ] Sort Colors
  8. Java多线程编程&lt;一&gt;
  9. inline-block间隔问题
  10. yii2邮件配置教程,报Expected response code 250 but got code &quot;553&quot;原因
  11. [COGS 2051] 王者之剑
  12. PHP 判断Header 送出前, 是否有值被送出去: headers_sent()
  13. javascript之event对象
  14. Element老司机开车了
  15. 4.3 thymeleaf模板引擎的使用
  16. Docker(二)搭建和使用Docker
  17. 1.RN环境搭建,创建项目,使用夜神模拟调试
  18. 1094 和为k的连续区间(暴力)
  19. Python 2和Python 3的编码问题
  20. VSCode和VUE的初始安装及简单使用入门

热门文章

  1. hdu 2100
  2. POJ1635 树的最小表示法(判断同构)
  3. 「CodePlus 2018 3 月赛」白金元首与莫斯科
  4. calc BZOJ 2655
  5. thinkphp框架做项目的前期配置
  6. docker镜像mac下保存路径
  7. 2-sat问题,输出方案,几种方法(赵爽的论文染色解法+其完全改进版)浅析 / POJ3683
  8. Jenkins持续部署-Windows环境持续部署探究1
  9. Nginx官方配置文档收集
  10. 新闻:融资600万 他用一套系统优化15大HR工作场景 精简入转调离 月开通214家 | IT桔子