对于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.          intret; 
  15.          structbl_trig_notifier *n; 
  16. n= kzalloc(sizeof(struct bl_trig_notifier), GFP_KERNEL); 
  17.          led->trigger_data= n; 
  18.          if(!n) { 
  19.                    dev_err(led->dev,"unable to allocate backlight trigger\n"); 
  20.                    return; 
  21.          } 
  22. ret= device_create_file(led->dev, &dev_attr_inverted); 
  23.          if(ret) 
  24.                    gotoerr_invert; 
  25.          n->led= led; 
  26.          n->brightness= led->brightness; 
  27.          n->old_status= UNBLANK; 
  28.          n->notifier.notifier_call= fb_notifier_callback; 
  29. ret= fb_register_client(&n->notifier); 
  30.          if(ret) 
  31.                    dev_err(led->dev,"unable to register backlight trigger\n"); 
  32.          return; 
  33. err_invert: 
  34.          led->trigger_data= NULL; 
  35.          kfree(n); 

其中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.          structbl_trig_notifier *n = container_of(p, 
  4.                                                structbl_trig_notifier, notifier); 
  5.          struct led_classdev*led = n->led; 
  6.          struct fb_event*fb_event = data; 
  7.          int *blank =fb_event->data; 
  8.          int new_status =*blank ? BLANK : UNBLANK; 
  9.          switch (event) { 
  10.          case FB_EVENT_BLANK : 
  11.                    if(new_status == n->old_status) 
  12.                             break; 
  13.                    if((n->old_status == UNBLANK) ^ n->invert) { 
  14.                             n->brightness= led->brightness; 
  15.                             led_set_brightness(led,LED_OFF); 
  16.                    } else { 
  17.                             led_set_brightness(led,n->brightness); 
  18.                    } 
  19.                    n->old_status= new_status; 
  20.                    break; 
  21.          } 
  22.          return 0; 
  23. }  

如果触发了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.                            int rc; 
  8.                            led_cdev->trigger_data= NULL; 
  9. rc =device_create_file(led_cdev->dev, &dev_attr_delay_on); 
  10.                            if (rc) 
  11.                             return; 
  12. rc =device_create_file(led_cdev->dev, &dev_attr_delay_off); 
  13.                            if (rc) 
  14.                             gotoerr_out_delayon; 
  15.                            led_blink_set(led_cdev,&led_cdev->blink_delay_on, 
  16.                                   &led_cdev->blink_delay_off); 
  17.                            led_cdev->trigger_data= (void *)1; 
  18.                            return; 
  19. err_out_delayon: 
  20.                            device_remove_file(led_cdev->dev,&dev_attr_delay_on); 

当某个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.                            structheartbeat_trig_data *heartbeat_data; 
  13. heartbeat_data =kzalloc(sizeof(*heartbeat_data), GFP_KERNEL); 
  14.                            if (!heartbeat_data) 
  15.                             return; 
  16.                            led_cdev->trigger_data= heartbeat_data; 
  17.                            setup_timer(&heartbeat_data->timer, 
  18.                                 led_heartbeat_function, (unsigned long)led_cdev); 
  19.                            heartbeat_data->phase= 0; 
  20.                            led_heartbeat_function(heartbeat_data->timer.data); 

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

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

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

5、ide-disk

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

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

     以上便是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. luogu3755 [CQOI2017]老C的任务

    扫描线水题. #include <algorithm> #include <iostream> #include <cstdio> using namespace ...

  2. BRVAH(让RecyclerView变得更高效) (3)

    本文来自网易云社区 作者:吴思博 3 实现列表加载动画效果    3.1默认动画 我们只需将自建的 adapter 继承它对应满足需求的 Adapter,然后在 Activity 中实例化,通过ope ...

  3. 六 、harbor使用

    1 登录harbor docker login 10.1.2.6 2 打上标签 docker tag e3a875d407cf 10.1.2.6/library/ctf3:xss01 3 push到h ...

  4. POJ 1056 IMMEDIATE DECODABILITY

    IMMEDIATE DECODABILITY Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 9630   Accepted: ...

  5. [UOJ#128][BZOJ4196][Noi2015]软件包管理器

    [UOJ#128][BZOJ4196][Noi2015]软件包管理器 试题描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管 ...

  6. SGU 275 To xor or not to xor【最大xor和 高斯消元】

    题目大意:给你n个数(n<=100)要你找出若干个数使他们的异或和最大 思路:高斯-若当消元消完以后削成若干个独立的行向量,将它们异或起来就好 #include<cstdio> #i ...

  7. 将一个list均分成n个list

    /** * 将一个list均分成n个list,主要通过偏移量来实现的 * @param source * @return */ public <T> List<List<T&g ...

  8. COdevs 天梯 水题系列

    1203 判断浮点数是否相等 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 青铜 Bronze 题目描述 Description 给出两个浮点数,请你判断这两个浮点数是否相等 输入 ...

  9. 转载自CSDN,结论:windows下按ENTER键应该是\r\n ascii码为 13 10

    记得在Windows下学X86汇编语言时,用0DH(\r)和0AH(\n)来输出回车(跳到下一行的开始处).问题来了,在Windows下是 先回车再换行呢还是先换行再回车呢?在Unix系统下换行只有\ ...

  10. Info.plist 的字段解释

    bundle字段 这些字段名都是XML中的名称,在xcode的属性编辑器中,名字并不相同 bundle目录中的属性列表详细描述了有关该bundle的信息.Finder和一些系统API在一些情况下会使用 ...