Linux内核LED模块分析(二)
上次分析到那里后,还是有些同志说看不懂,那我就继续分析一把我认为不需要继续分析的东西吧。上回分析了

led_cdev和trigger的关系后就没有继续说了。有同志还是没明白怎么调用的。干活的函数是:
static void led_heartbeat_function(unsigned long data)
{
 struct led_classdev *led_cdev = (struct led_classdev *) data;
 struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
 unsigned long brightness = LED_OFF;
 unsigned long delay = 0;

/* acts like an actual heart beat -- ie thump-thump-pause... */
 switch (heartbeat_data->phase) {
 case 0:
  /*
   * The hyperbolic function below modifies the
   * heartbeat period length in dependency of the
   * current (1min) load. It goes through the points
   * f(0)=1260, f(1)=860, f(5)=510, f(inf)->300.
   */
  heartbeat_data->period = 300 +
   (6720 << FSHIFT) / (5 * avenrun[0] + (7 << FSHIFT));
  heartbeat_data->period =
   msecs_to_jiffies(heartbeat_data->period);
  delay = msecs_to_jiffies(70);
  heartbeat_data->phase++;
  brightness = led_cdev->max_brightness;
  break;
 case 1:
  delay = heartbeat_data->period / 4 - msecs_to_jiffies(70);
  heartbeat_data->phase++;
  break;
 case 2:
  delay = msecs_to_jiffies(70);
  heartbeat_data->phase++;
  brightness = led_cdev->max_brightness;
  break;
 default:
  delay = heartbeat_data->period - heartbeat_data->period / 4 -
   msecs_to_jiffies(70);
  heartbeat_data->phase = 0;
  break;
 }

led_set_brightness(led_cdev, brightness);
 mod_timer(&heartbeat_data->timer, jiffies + delay);
}
这个函数里面调用了led_set_brightness(led_cdev, brightness);
static inline void led_set_brightness(struct led_classdev *led_cdev,
     enum led_brightness value)
{
 if (value > led_cdev->max_brightness)
  value = led_cdev->max_brightness;
 led_cdev->brightness = value;
 if (!(led_cdev->flags & LED_SUSPENDED))
  led_cdev->brightness_set(led_cdev, value);
}
很明显这个函数调用了led_cdev->brightness_set(led_cdev, value);
这个就是我们在leds-sunfire.c中注册的led_cdev。
我们回过头想一想我们刚开始注册led_cdev的过程:
static int __devinit sunfire_led_generic_probe(struct platform_device *pdev,
            struct led_type *types)
{
 struct sunfire_drvdata *p;
 int i, err = -EINVAL;

if (pdev->num_resources != 1) {
  printk(KERN_ERR PFX "Wrong number of resources %d, should be 1/n",
         pdev->num_resources);
  goto out;
 }

p = kzalloc(sizeof(*p), GFP_KERNEL);
 if (!p) {
  printk(KERN_ERR PFX "Could not allocate struct sunfire_drvdata/n");
  goto out;
 }

for (i = 0; i < NUM_LEDS_PER_BOARD; i++) {
  struct led_classdev *lp = &p->leds[i].led_cdev;

p->leds[i].reg = (void __iomem *) pdev->resource[0].start;
  lp->name = types[i].name;
  lp->brightness = LED_FULL;
  lp->brightness_set = types[i].handler;
  lp->default_trigger = types[i].default_trigger;

err = led_classdev_register(&pdev->dev, lp);
  if (err) {
   printk(KERN_ERR PFX "Could not register %s LED/n",
          lp->name);
   goto out_unregister_led_cdevs;
  }
 }

dev_set_drvdata(&pdev->dev, p);

err = 0;
out:
 return err;

out_unregister_led_cdevs:
 for (i--; i >= 0; i--)
  led_classdev_unregister(&p->leds[i].led_cdev);
 goto out;
}
看到了吧:
or (i = 0; i < NUM_LEDS_PER_BOARD; i++) {
  struct led_classdev *lp = &p->leds[i].led_cdev;

p->leds[i].reg = (void __iomem *) pdev->resource[0].start;
  lp->name = types[i].name;
  lp->brightness = LED_FULL;
  lp->brightness_set = types[i].handler;
  lp->default_trigger = types[i].default_trigger;

err = led_classdev_register(&pdev->dev, lp);
  if (err) {
   printk(KERN_ERR PFX "Could not register %s LED/n",
          lp->name);
   goto out_unregister_led_cdevs;
  }
 }
这时候就会将我们的handle函数挂在led_cdev的brightness_set。所以我们最终调用的是:
static struct led_type clockboard_led_types[NUM_LEDS_PER_BOARD] = {
 {
  .name  = "clockboard-left",
  .handler = clockboard_left_set,
 },
 {
  .name  = "clockboard-middle",
  .handler = clockboard_middle_set,
 },
 {
  .name  = "clockboard-right",
  .handler = clockboard_right_set,
  .default_trigger= "heartbeat",
 },
};
这个结构体数组中第三个成员的handler函数。
也就是clockboard_right_set()。
static void clockboard_right_set(struct led_classdev *led_cdev,
     enum led_brightness led_val)
{
 __clockboard_set(led_cdev, led_val, CLOCK_CTRL_RLED);
}
static void __clockboard_set(struct led_classdev *led_cdev,
        enum led_brightness led_val, u8 bit)
{
 struct sunfire_led *p = to_sunfire_led(led_cdev);
 u8 reg = upa_readb(p->reg);

switch (bit) {
 case CLOCK_CTRL_LLED:
  if (led_val)
   reg &= ~bit;
  else
   reg |= bit;
  break;

default:
  if (led_val)
   reg |= bit;
  else
   reg &= ~bit;
  break;
 }
 upa_writeb(reg, p->reg);
}
这个就是写寄存器了。OK。总算分析完了,还不明白就没办法了。^_^

Linux内核LED模块分析(二)相关推荐

  1. linux内核netfilter模块分析之:HOOKs点的注册及调用

    1: 为什么要写这个东西? 最近在找工作,之前netfilter 这一块的代码也认真地研究过,应该每个人都是这样的你懂 不一定你能很准确的表达出来. 故一定要化些时间把这相关的东西总结一下. 0:相关 ...

  2. Linux 内核源代码情景分析(二)

    系列文章目录 Linux 内核设计与实现 深入理解 Linux 内核 Linux 设备驱动程序 Linux设备驱动开发详解 深入理解Linux虚拟内存管理 Linux 内核源代码情景分析(一) Lin ...

  3. Linux内核源代码情景分析笔记

    Linux内核源代码情景分析笔记 好吧,首先我承认我要是读者的话,这篇文章我看着也头疼,因为写的太长太泛(其主要部分集中在内存管理,进程管理,文件系统)!原本是想按自己理解的精简精简的,按照操作系统中 ...

  4. Linux内核源码分析方法—程序员进阶必备

    一.内核源码之我见 Linux内核代码的庞大令不少人"望而生畏",也正因为如此,使得人们对Linux的了解仅处于泛泛的层次.如果想透析Linux,深入操作系统的本质,阅读内核源码是 ...

  5. linux内核源码分析笔记

    一.内核源码目录结构 1.Linux 内核源代码包括三个主要部分 1)内核核心代码:包括linux内核整体架构分析笔记描述的各子系统和子模块,以及其他支撑子系统,如:电源管理.linux初始化等. 2 ...

  6. Linux内核启动流程分析(一)【转】

    转自:http://blog.chinaunix.net/uid-25909619-id-3380535.html 很久以前分析的,一直在电脑的一个角落,今天发现贴出来和大家分享下.由于是word直接 ...

  7. 2017-2018-1 20179215《Linux内核原理与分析》第二周作业

    20179215<Linux内核原理与分析>第二周作业 这一周主要了解了计算机是如何工作的,包括现在存储程序计算机的工作模型.X86汇编指令包括几种内存地址的寻址方式和push.pop.c ...

  8. 2018-2019-1 20189213《Linux内核原理与分析》第四周作业

    <Linux内核原理与分析>第四周学习总结: 1.课本知识总结: 本章内容并不多,首先是介绍了一些Linux内核源代码的目录结构,并基于Linux内核源代码构造一个简单的操作系统MenuO ...

  9. linux 虚拟文件系统 源码,Linux内核源代码情状分析-虚拟文件系统

    Linux内核源代码情景分析-虚拟文件系统 我们先来看两张图: 第一张是VFS与具体文件系统的关系示意图: 第二张是Linux文件系统的层次结构: 特殊文件:用来实现"管道"的文件 ...

最新文章

  1. 如何在页面上实现一个圆形的可点击区域?
  2. 强类型DataSet中的DBNull的处理
  3. docker停止容器,删除镜像常用指令
  4. 弹性盒子 flex-direction
  5. Spring Boot(二)应用实例
  6. JavaScript 之 动态加载JS代码或JS文件
  7. Pytorch中的 torch.as_tensor() 和 torch.from_numpy() 的区别
  8. 安卓开发必须会的技能!浅谈Android消息机制原理,威力加强版
  9. 苏宁回应“股权质押”:正常商业合作
  10. 统计字符串中每个字符的个数_C++程序设计——统计数字字符个数
  11. JAVA程序获取Tomcat的运行状态
  12. 小程序uniapp基础
  13. (三)JAVA使用POI操作excel
  14. 风控中英文术语手册(银行_消费金融信贷业务)_version6
  15. a form 出口享惠情况_关税聚焦 | 报关单“出口享惠情况”填报解读
  16. 多窗口键盘鼠标同步软件
  17. 微软私有云服务器,微软私有云
  18. win7调整屏幕亮度_win7系统设置护眼色后,不生效怎么办?
  19. linux 多个ftp站点,vsftp在虚拟主机上建立多个ftp站点
  20. java mp3合并_java合并MP3文件

热门文章

  1. 已经开发好的网站,进行多语言支持
  2. 数据家新三板挂牌上市
  3. php laravel 教程,Laravel 入门到精通教程
  4. 数据库系统概念 | 第六章:形式化关系查询语言 | 含带答案习题
  5. VUE组件通信的使用
  6. Xilinx 7系列FPGA中CLB结构和内部资源使用
  7. python中可选参数如何指定_Python可选参数
  8. ireport 5.6.0的常见使用及开发报表中经常遇到的问题总结
  9. redis命令---redist键命令(key)---redis字符串命令(str)
  10. 【论文笔记】LARA:基于GAN的解决冷启动问题的推荐系统