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

1、default-on

static void defon_trig_activate(struct led_classdev *led_cdev)
{
    led_set_brightness(led_cdev, led_cdev->max_brightness);
}

static struct led_trigger defon_led_trigger = {
    .name     = "default-on",
    .activate = defon_trig_activate,
};

static int __init defon_trig_init(void)
{
    return led_trigger_register(&defon_led_trigger);
}

static void __exit defon_trig_exit(void)
{
    led_trigger_unregister(&defon_led_trigger);
}

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的一些简单介绍。

linux led子系统(二)的更多相关文章

  1. 初探linux子系统集之led子系统(二)

    巴西世界杯,德国7比1东道主,那个惨不忍睹啊,早上起来看新闻,第一眼看到7:1还以为点球也能踢成这样,后来想想,点球对多嘛6比1啊,接着就是各种新闻铺天盖地的来了.其实失败并没有什么,人生若是能够成功 ...

  2. 初探linux子系统集之led子系统(二)【转】

    本文转载自:http://blog.csdn.net/eastmoon502136/article/details/37606487 巴西世界杯,德国7比1东道主,那个惨不忍睹啊,早上起来看新闻,第一 ...

  3. linux led子系统(一)

    就像学编程第一个范例helloworld一样,学嵌入式,单片机.fpga之类的第一个范例就是点亮一盏灯.对于庞大的linux系统,当然可以编写一个字符设备驱动来实现我们需要的led灯,也可以直接利用g ...

  4. Linux时间子系统(二) 软件架构

    一.前言 本文的主要内容是描述内核时间子系统的软件框架.首先介绍了从旧的时间子系统迁移到新的时间子系统的源由,介绍新的时间子系统的优势.第三章汇整了时间子系统的相关文件以及内核配置.最后描述各种内核配 ...

  5. (linux)LED子系统

    数据结构(/include/linux/leds.h) enum led_brightness { LED_OFF = 0, LED_HALF = 127, LED_FULL = 255, }; le ...

  6. Linux usb子系统(二) _usb-skeleton.c精析

    "./drivers/usb/usb-skeleton.c"是内核提供给usb设备驱动开发者的海量存储usb设备的模板程序, 程序不长, 通用性却很强,十分经典, 深入理解这个文件 ...

  7. Linux i2c子系统(二) _通过i2c-dev.c访问设备的方法

    另外一种驱动 应用层除了使用上述的使用i2c_driver接口来访问i2c设备,Linux内核还提供了一种简单粗暴的方式--直接通过虚拟i2c设备驱动的方式,即上一篇中的i2c-dev提供的方式,这种 ...

  8. 初探linux子系统集之led子系统(一)

    就像学编程第一个范例helloworld一样,学嵌入式,单片机.fpga之类的第一个范例就是点亮一盏灯.对于庞大的linux系统,当然可以编写一个字符设备驱动来实现我们需要的led灯,也可以直接利用g ...

  9. Linux时间子系统之(二):软件架构

    专题文档汇总目录 Notes:从框架上讲解了时间子系统,从底向上包括CPU Local TImer.Global Counter.Clock Souce/Clock Events模块管理.Tick D ...

随机推荐

  1. Non-maximum suppression(非极大值抑制算法)

    在RCNN系列目标检测中,有一个重要的算法,用于消除一些冗余的bounding box,这就是non-maximum suppression算法. 这里有一篇博客写的挺好的: http://www.c ...

  2. 【转】Python3学习笔记(urllib模块的使用)

    原文地址:https://www.cnblogs.com/Lands-ljk/p/5447127.html 1.基本方法 urllib.request.urlopen(url, data=None,  ...

  3. BZOJ 2331 [SCOI2011]地板 ——插头DP

    [题目分析] 经典题目,插头DP. switch 套 switch 代码瞬间清爽了. [代码] #include <cstdio> #include <cstring> #in ...

  4. (2015大作业)茹何优雅的手写正则表达式引擎(regular expression engine

    貌似刚开学的时候装了个逼,和老师立了个flag说我要写个正则表达式引擎,然后学期末估计老师早就忘了这茬了,在历时3个月的懒癌发作下,终于在这学期末deadline的时候花了一个下午加晚上在没有网的房间 ...

  5. 【DFS求树的最大二分匹配+输入外挂】HDU 6178 Monkeys

    http://acm.hdu.edu.cn/showproblem.php?pid=6178 [题意] 给定一棵有n个结点的树,现在有k个猴子分布在k个结点上,我们可以删去树上的一些边,使得k个猴子每 ...

  6. OSI模型详解

    OSI 七层模型通过七个层次化的结构模型使不同的系统不同的网络之间实现可靠的通讯,因此其最主要的功能就是帮助不同类型的主机实现数据传输 . 完成中继功能的节点通常称为中继系统.在OSI七层模型中,处于 ...

  7. CentOS 7.5 初始网络配置

    最近刚装完 CentOS 7.5 系统,由于网络不通,导致无法用 yum 命令下载软件,经过了各种折腾,终于搞定了,这里讲解一下 如何设置初始网络. 本案例环境  VmWare 11.0 , 操作系统 ...

  8. T1077 多源最短路 codevs

    http://codevs.cn/problem/1077/ 时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题目描述 Description 已知n个点(n&l ...

  9. Spring中Bean的后置处理器

    以下内容引用自http://wiki.jikexueyuan.com/project/spring/bean-post-processors.html: Bean后置处理器 BeanPostProce ...

  10. for 循环进化史

    ECMAScript 6已经逐渐普及,经过二十多年的改进,很多功能也有了更成熟的语句,比如 for 循环 这篇博客将介绍一下从最初的 for 循环,到 ES6 的 for-of 等四种遍历方法 先定义 ...