Linux内核LED模块分析(二)
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模块分析(二)相关推荐
- linux内核netfilter模块分析之:HOOKs点的注册及调用
1: 为什么要写这个东西? 最近在找工作,之前netfilter 这一块的代码也认真地研究过,应该每个人都是这样的你懂 不一定你能很准确的表达出来. 故一定要化些时间把这相关的东西总结一下. 0:相关 ...
- Linux 内核源代码情景分析(二)
系列文章目录 Linux 内核设计与实现 深入理解 Linux 内核 Linux 设备驱动程序 Linux设备驱动开发详解 深入理解Linux虚拟内存管理 Linux 内核源代码情景分析(一) Lin ...
- Linux内核源代码情景分析笔记
Linux内核源代码情景分析笔记 好吧,首先我承认我要是读者的话,这篇文章我看着也头疼,因为写的太长太泛(其主要部分集中在内存管理,进程管理,文件系统)!原本是想按自己理解的精简精简的,按照操作系统中 ...
- Linux内核源码分析方法—程序员进阶必备
一.内核源码之我见 Linux内核代码的庞大令不少人"望而生畏",也正因为如此,使得人们对Linux的了解仅处于泛泛的层次.如果想透析Linux,深入操作系统的本质,阅读内核源码是 ...
- linux内核源码分析笔记
一.内核源码目录结构 1.Linux 内核源代码包括三个主要部分 1)内核核心代码:包括linux内核整体架构分析笔记描述的各子系统和子模块,以及其他支撑子系统,如:电源管理.linux初始化等. 2 ...
- Linux内核启动流程分析(一)【转】
转自:http://blog.chinaunix.net/uid-25909619-id-3380535.html 很久以前分析的,一直在电脑的一个角落,今天发现贴出来和大家分享下.由于是word直接 ...
- 2017-2018-1 20179215《Linux内核原理与分析》第二周作业
20179215<Linux内核原理与分析>第二周作业 这一周主要了解了计算机是如何工作的,包括现在存储程序计算机的工作模型.X86汇编指令包括几种内存地址的寻址方式和push.pop.c ...
- 2018-2019-1 20189213《Linux内核原理与分析》第四周作业
<Linux内核原理与分析>第四周学习总结: 1.课本知识总结: 本章内容并不多,首先是介绍了一些Linux内核源代码的目录结构,并基于Linux内核源代码构造一个简单的操作系统MenuO ...
- linux 虚拟文件系统 源码,Linux内核源代码情状分析-虚拟文件系统
Linux内核源代码情景分析-虚拟文件系统 我们先来看两张图: 第一张是VFS与具体文件系统的关系示意图: 第二张是Linux文件系统的层次结构: 特殊文件:用来实现"管道"的文件 ...
最新文章
- 如何在页面上实现一个圆形的可点击区域?
- 强类型DataSet中的DBNull的处理
- docker停止容器,删除镜像常用指令
- 弹性盒子 flex-direction
- Spring Boot(二)应用实例
- JavaScript 之 动态加载JS代码或JS文件
- Pytorch中的 torch.as_tensor() 和 torch.from_numpy() 的区别
- 安卓开发必须会的技能!浅谈Android消息机制原理,威力加强版
- 苏宁回应“股权质押”:正常商业合作
- 统计字符串中每个字符的个数_C++程序设计——统计数字字符个数
- JAVA程序获取Tomcat的运行状态
- 小程序uniapp基础
- (三)JAVA使用POI操作excel
- 风控中英文术语手册(银行_消费金融信贷业务)_version6
- a form 出口享惠情况_关税聚焦 | 报关单“出口享惠情况”填报解读
- 多窗口键盘鼠标同步软件
- 微软私有云服务器,微软私有云
- win7调整屏幕亮度_win7系统设置护眼色后,不生效怎么办?
- linux 多个ftp站点,vsftp在虚拟主机上建立多个ftp站点
- java mp3合并_java合并MP3文件
热门文章
- 已经开发好的网站,进行多语言支持
- 数据家新三板挂牌上市
- php laravel 教程,Laravel 入门到精通教程
- 数据库系统概念 | 第六章:形式化关系查询语言 | 含带答案习题
- VUE组件通信的使用
- Xilinx 7系列FPGA中CLB结构和内部资源使用
- python中可选参数如何指定_Python可选参数
- ireport 5.6.0的常见使用及开发报表中经常遇到的问题总结
- redis命令---redist键命令(key)---redis字符串命令(str)
- 【论文笔记】LARA:基于GAN的解决冷启动问题的推荐系统