2013-06-17 16:28 287人阅读 评论(0) 收藏 举报

目录(?)[+]

  1. Android的Setting
  2. Android的背光JNI层
  3. Android的背光HAL层
  4. Linux的背光内核层
  5. Linux的背光驱动层
  6. 总结

其实Android的底层就是Linux,所以其驱动本质就是Linux驱动,但是这些Linux驱动是服务上层Android的,所以需遵循上Android的一些接口规范。所以涉及到的Android驱动都应应密切关注上层传递的接口。本文介绍的LCD背光驱动就是从上层一直往下层展现,但是笔者毕竟不是专注于Android上层,碍于知识不充裕,所以对上层的东西介绍得相对简单。

1.Android的Setting

亮度设置的java源文件在:
mydroid/packages/apps/Settings/src/com/android/settings/BrightnessPreference.java
打开这个文件看到:
[java] view plaincopy
  1. public class BrightnessPreference extends SeekBarDialogPreference implements
  2. SeekBar.OnSeekBarChangeListener, CheckBox.OnCheckedChangeListener {
  3. private SeekBar mSeekBar;
  4. private CheckBox mCheckBox;
  5. private int mOldBrightness;
  6. private int mOldAutomatic;
  7. private boolean mAutomaticAvailable;
  8. private boolean mRestoredOldState;
  9. // Backlight range is from 0 - 255. Need to make sure that user
  10. // doesn't set the backlight to 0 and get stuck
  11. private int mScreenBrightnessDim =
  12. ...
[java] view plaincopy
  1. public class BrightnessPreference extends SeekBarDialogPreference implements
  2. SeekBar.OnSeekBarChangeListener, CheckBox.OnCheckedChangeListener {
  3. private SeekBar mSeekBar;
  4. private CheckBox mCheckBox;
  5. private int mOldBrightness;
  6. private int mOldAutomatic;
  7. private boolean mAutomaticAvailable;
  8. private boolean mRestoredOldState;
  9. // Backlight range is from 0 - 255. Need to make sure that user
  10. // doesn't set the backlight to 0 and get stuck
  11. private int mScreenBrightnessDim =
  12. ...

Android的最上层已经将背光亮度量化为了[0,255]个等级,并且提示注意不要设置为0,所以在进行最低层的背光驱动编写时,可以合理按这个范围部署背光的亮度。

2.Android的背光JNI层

这一层就是调用HAL层的方法,为上一层实现一个设置亮度接口。

3.Android的背光HAL层

先浏览欣赏一下light.c先
[cpp] view plaincopy
  1. /*
  2. * Copyright (C) 2008 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. *      http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #define LOG_TAG "lights"
  17. #include <cutils/log.h>
  18. #include <stdint.h>
  19. #include <string.h>
  20. #include <unistd.h>
  21. #include <errno.h>
  22. #include <fcntl.h>
  23. #include <pthread.h>
  24. #include <sys/ioctl.h>
  25. #include <sys/types.h>
  26. #include <hardware/lights.h>
  27. /******************************************************************************/
  28. static pthread_once_t g_init = PTHREAD_ONCE_INIT;
  29. static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
  30. char const*const LCD_FILE
  31. = "/sys/class/leds/lcd-backlight/brightness";
  32. char const*const KEYBOARD_FILE
  33. = "/sys/class/leds/keyboard-backlight/brightness";
  34. char const*const CHARGING_LED_FILE
  35. = "/sys/class/leds/battery-led/brightness";
  36. /*RGB file descriptors */
  37. char const*const RED_LED_FILE
  38. = "/sys/class/leds/red/brightness";
  39. char const*const RED_DELAY_ON_FILE
  40. = "/sys/class/leds/red/delay_on";
  41. char const*const RED_DELAY_OFF_FILE
  42. = "/sys/class/leds/red/delay_off";
  43. char const*const GREEN_LED_FILE
  44. = "/sys/class/leds/green/brightness";
  45. char const*const GREEN_DELAY_ON_FILE
  46. = "/sys/class/leds/green/delay_on";
  47. char const*const GREEN_DELAY_OFF_FILE
  48. = "/sys/class/leds/green/delay_off";
  49. char const*const BLUE_LED_FILE
  50. = "/sys/class/leds/blue/brightness";
  51. char const*const BLUE_DELAY_ON_FILE
  52. = "/sys/class/leds/blue/delay_on";
  53. char const*const BLUE_DELAY_OFF_FILE
  54. = "/sys/class/leds/blue/delay_off";
  55. ...
[cpp] view plaincopy
  1. /*
  2. * Copyright (C) 2008 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. *      http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #define LOG_TAG "lights"
  17. #include <cutils/log.h>
  18. #include <stdint.h>
  19. #include <string.h>
  20. #include <unistd.h>
  21. #include <errno.h>
  22. #include <fcntl.h>
  23. #include <pthread.h>
  24. #include <sys/ioctl.h>
  25. #include <sys/types.h>
  26. #include <hardware/lights.h>
  27. /******************************************************************************/
  28. static pthread_once_t g_init = PTHREAD_ONCE_INIT;
  29. static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
  30. char const*const LCD_FILE
  31. = "/sys/class/leds/lcd-backlight/brightness";
  32. char const*const KEYBOARD_FILE
  33. = "/sys/class/leds/keyboard-backlight/brightness";
  34. char const*const CHARGING_LED_FILE
  35. = "/sys/class/leds/battery-led/brightness";
  36. /*RGB file descriptors */
  37. char const*const RED_LED_FILE
  38. = "/sys/class/leds/red/brightness";
  39. char const*const RED_DELAY_ON_FILE
  40. = "/sys/class/leds/red/delay_on";
  41. char const*const RED_DELAY_OFF_FILE
  42. = "/sys/class/leds/red/delay_off";
  43. char const*const GREEN_LED_FILE
  44. = "/sys/class/leds/green/brightness";
  45. char const*const GREEN_DELAY_ON_FILE
  46. = "/sys/class/leds/green/delay_on";
  47. char const*const GREEN_DELAY_OFF_FILE
  48. = "/sys/class/leds/green/delay_off";
  49. char const*const BLUE_LED_FILE
  50. = "/sys/class/leds/blue/brightness";
  51. char const*const BLUE_DELAY_ON_FILE
  52. = "/sys/class/leds/blue/delay_on";
  53. char const*const BLUE_DELAY_OFF_FILE
  54. = "/sys/class/leds/blue/delay_off";
  55. ...
[cpp] view plaincopy
  1. static int
  2. set_light_backlight(struct light_device_t* dev,
  3. struct light_state_t const* state)
  4. {
  5. int err = 0;
  6. int brightness = rgb_to_brightness(state);
  7. pthread_mutex_lock(&g_lock);
  8. err = write_int(LCD_FILE, brightness);
  9. pthread_mutex_unlock(&g_lock);
  10. return err;
  11. }
[cpp] view plaincopy
  1. static int
  2. set_light_backlight(struct light_device_t* dev,
  3. struct light_state_t const* state)
  4. {
  5. int err = 0;
  6. int brightness = rgb_to_brightness(state);
  7. pthread_mutex_lock(&g_lock);
  8. err = write_int(LCD_FILE, brightness);
  9. pthread_mutex_unlock(&g_lock);
  10. return err;
  11. }

这里关注一下LCD背光的sys文件节点:"/sys/class/leds/lcd-backlight/brightness"

疑问1:这个sys接口是谁约定的呢?
疑问2:可不可以改这个接口呢?
疑问3:为什么这里还有其他led的很多sys文件节点呢:
先解释疑问3,因为一个Android设备,不只是有LCD背光的LED,还有可以有其他很多LED(当然也可以没有),所以这里一并实现了这些LED的HAL,产品商可以沿用这些HAL。
先来试验一把:
启动Android设备,在Setting里更改亮度,然后在串口命令行中或“adb shell"中运行命令cat /sys/class/leds/lcd-backlight/brightness,会发现Setting的更改后可以通过cat 显示Setting的更改。所以更加确认了这个"/sys/class/leds/lcd-backlight/brightness"接口是正确的。
因为HAL层是和Linux Kernel交互的,所以这里如果能cat实现读取亮度等级,那么在Linux kernel层就一定实现了sysfs接口。

4.Linux的背光内核层

[cpp] view plaincopy
  1. static int __init leds_init(void)
  2. {
  3. leds_class = class_create(THIS_MODULE, "leds");
  4. if (IS_ERR(leds_class))
  5. return PTR_ERR(leds_class);
  6. leds_class->suspend = led_suspend;
  7. leds_class->resume = led_resume;
  8. leds_class->dev_attrs = led_class_attrs;
  9. return 0;
  10. }
[cpp] view plaincopy
  1. static int __init leds_init(void)
  2. {
  3. leds_class = class_create(THIS_MODULE, "leds");
  4. if (IS_ERR(leds_class))
  5. return PTR_ERR(leds_class);
  6. leds_class->suspend = led_suspend;
  7. leds_class->resume = led_resume;
  8. leds_class->dev_attrs = led_class_attrs;
  9. return 0;
  10. }

好明显,正是由于它创建了sys class,名字为”leds“,所以上面的背光sys文件节点"/sys/class/leds/”就有了来由,那么剩下的“../lcd-backlight/brightness"又是怎么来的呢?看看一个注册led设备类的函数.

[cpp] view plaincopy
  1. /**
  2. * led_classdev_register - register a new object of led_classdev class.
  3. * @parent: The device to register.
  4. * @led_cdev: the led_classdev structure for this device.
  5. */
  6. int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
  7. {
  8. led_cdev->dev = device_create(leds_class, parent, 0, led_cdev,
  9. "%s", led_cdev->name);
  10. if (IS_ERR(led_cdev->dev))
  11. return PTR_ERR(led_cdev->dev);
  12. #ifdef CONFIG_LEDS_TRIGGERS
  13. init_rwsem(&led_cdev->trigger_lock);
  14. ...
[cpp] view plaincopy
  1. /**
  2. * led_classdev_register - register a new object of led_classdev class.
  3. * @parent: The device to register.
  4. * @led_cdev: the led_classdev structure for this device.
  5. */
  6. int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
  7. {
  8. led_cdev->dev = device_create(leds_class, parent, 0, led_cdev,
  9. "%s", led_cdev->name);
  10. if (IS_ERR(led_cdev->dev))
  11. return PTR_ERR(led_cdev->dev);
  12. #ifdef CONFIG_LEDS_TRIGGERS
  13. init_rwsem(&led_cdev->trigger_lock);
  14. ...

这个注册函数的接口最终会被我们要开发的背光驱动调用,这个接口在/sys/class/leds/下又创建了一个设备接口,名字是led_cdev->name。好明显这里的led_cdev->name应该就是”lcd-backlight“,究竟是不是真的这样呢?继续看。

这个led-class.c在实现两个设备属性,看代码:
[cpp] view plaincopy
  1. static struct device_attribute led_class_attrs[] = {
  2. __ATTR(brightness, 0644, led_brightness_show, led_brightness_store),
  3. __ATTR(max_brightness, 0444, led_max_brightness_show, NULL),
  4. #ifdef CONFIG_LEDS_TRIGGERS
  5. __ATTR(trigger, 0644, led_trigger_show, led_trigger_store),
  6. #endif
  7. __ATTR_NULL,
  8. };
[cpp] view plaincopy
  1. static struct device_attribute led_class_attrs[] = {
  2. __ATTR(brightness, 0644, led_brightness_show, led_brightness_store),
  3. __ATTR(max_brightness, 0444, led_max_brightness_show, NULL),
  4. #ifdef CONFIG_LEDS_TRIGGERS
  5. __ATTR(trigger, 0644, led_trigger_show, led_trigger_store),
  6. #endif
  7. __ATTR_NULL,
  8. };

看到了属性名字为”brightness“,这似乎越来越接近解释"/sys/class/leds/lcd-backlight/brightness"的由来了。

[cpp] view plaincopy
  1. struct display_led_data {
  2. struct led_classdev pri_display_class_dev;
  3. struct led_classdev sec_display_class_dev;
  4. struct omap4_disp_led_platform_data *led_pdata;
  5. struct mutex pri_disp_lock;
  6. struct mutex sec_disp_lock;
  7. };
  8. static int omap4_XXX_display_probe(struct platform_device *pdev)
  9. {
  10. int ret;
  11. struct display_led_data *info;
  12. pr_info("%s:Enter\n", __func__);
  13. if (pdev->dev.platform_data == NULL) {
  14. pr_err("%s: platform data required\n", __func__);
  15. return -ENODEV;
  16. }
  17. info = kzalloc(sizeof(struct display_led_data), GFP_KERNEL);
  18. if (info == NULL) {
  19. ret = -ENOMEM;
  20. return ret;
  21. }
  22. info->led_pdata = pdev->dev.platform_data;
  23. platform_set_drvdata(pdev, info);
  24. info->pri_display_class_dev.name = "lcd-backlight";
  25. info->pri_display_class_dev.brightness_set = omap4_xxx_primary_disp_store;
  26. ...
  27. ret = led_classdev_register(&pdev->dev,
  28. &info->pri_display_class_dev);
  29. if (ret < 0) {
  30. pr_err("%s: Register led class failed\n", __func__);
  31. kfree(info);
  32. return ret;
  33. }
  34. if (info->led_pdata->flags & LEDS_CTRL_AS_TWO_DISPLAYS) {
  35. pr_info("%s: Configuring the secondary LED\n", __func__);
  36. info->sec_display_class_dev.name = "lcd-backlight2";
  37. info->sec_display_class_dev.brightness_set =
  38. omap4_mirage_secondary_disp_store;
  39. info->sec_display_class_dev.max_brightness = LED_OFF;
  40. mutex_init(&info->sec_disp_lock);
  41. ret = led_classdev_register(&pdev->dev,
  42. &info->sec_display_class_dev);
  43. ...
[cpp] view plaincopy
  1. struct display_led_data {
  2. struct led_classdev pri_display_class_dev;
  3. struct led_classdev sec_display_class_dev;
  4. struct omap4_disp_led_platform_data *led_pdata;
  5. struct mutex pri_disp_lock;
  6. struct mutex sec_disp_lock;
  7. };
  8. static int omap4_XXX_display_probe(struct platform_device *pdev)
  9. {
  10. int ret;
  11. struct display_led_data *info;
  12. pr_info("%s:Enter\n", __func__);
  13. if (pdev->dev.platform_data == NULL) {
  14. pr_err("%s: platform data required\n", __func__);
  15. return -ENODEV;
  16. }
  17. info = kzalloc(sizeof(struct display_led_data), GFP_KERNEL);
  18. if (info == NULL) {
  19. ret = -ENOMEM;
  20. return ret;
  21. }
  22. info->led_pdata = pdev->dev.platform_data;
  23. platform_set_drvdata(pdev, info);
  24. info->pri_display_class_dev.name = "lcd-backlight";
  25. info->pri_display_class_dev.brightness_set = omap4_xxx_primary_disp_store;
  26. ...
  27. ret = led_classdev_register(&pdev->dev,
  28. &info->pri_display_class_dev);
  29. if (ret < 0) {
  30. pr_err("%s: Register led class failed\n", __func__);
  31. kfree(info);
  32. return ret;
  33. }
  34. if (info->led_pdata->flags & LEDS_CTRL_AS_TWO_DISPLAYS) {
  35. pr_info("%s: Configuring the secondary LED\n", __func__);
  36. info->sec_display_class_dev.name = "lcd-backlight2";
  37. info->sec_display_class_dev.brightness_set =
  38. omap4_mirage_secondary_disp_store;
  39. info->sec_display_class_dev.max_brightness = LED_OFF;
  40. mutex_init(&info->sec_disp_lock);
  41. ret = led_classdev_register(&pdev->dev,
  42. &info->sec_display_class_dev);
  43. ...


需关注这里设置了info->pri_display_class_dev.name = "lcd-backlight";,然后调用led_classdev_register函数注册,所以完美解释了
led_cdev->name就是 "lcd-backlight",完美解释了"/sys/class/leds/lcd-backlight/brightness"的由来。
另外info->pri_display_class_dev.brightness_set = omap4_xxx_primary_disp_store;中的omap4_xxx_primary_disp_store()就是我们需要实现的设置背光亮度函数,函数里面就是pwm操作。
到这里又有一个疑问4:为什么只实现设置背光亮度的接口,而没有实现读取当前亮度量化值的接口?
其实Android上层自行处理了这个获取亮度量化值的事情,也就是说Android上层设置了亮度是多少,上层会执行保留设置结果。无需再通过下层读取。

6.总结

android中的背光驱动层次分析相关推荐

  1. android中倒计时控件CountDownTimer分析

    android中倒计时控件CountDownTimer分析1 示例代码 new CountDownTimer(10000, 1000) {public void onTick(long millisU ...

  2. Android中app卡顿原因分析示例

    http://www.cnblogs.com/zhucai/p/weibo-graphics-performance-analyse.html 朱才 专注于Android图形动画 MIUI工程师 博客 ...

  3. android viewgroup 事件,android中viewgroup的事件传递分析

    在上一篇中我们分析了从view的dispatchTouchEvent到onTouchListener的onTouch回调到onTouchEvent到onClickLisener的onClickandr ...

  4. Android中启动Activity(startActivity)流程图分析

    在上篇博文< Android中ActivityManagerService与应用程序(客户端)通信模型分析>中,我们从宏观架构上掌握 ActivityManagerService与应用程序 ...

  5. Android中init与受精卵Zygote分析,以及添加自己开机启动的系统服务

    最近在做云游戏的项目,由于需要购买硬件,系统提供Android源码需要自己编译.所以特地学习一下记录一下Android的启动(我的是AOSP7.1然后+厂商系统补丁) 先上图: 目录 一. 启动流程硬 ...

  6. Android 中的混音器 AudioMixer 实现分析

    Android framework 的音频处理模库 libaudioprocessing (位于 frameworks/av/media/libaudioprocessing) 提供了混音器组件 Au ...

  7. Android中ViewStub的使用与分析

    文章目录 1.ViewStub的简单使用 1.1 简单说明 1.2 简单示例 2.结合源码分析问题 2.1 第二次调用inflate()加载会抛出空指针异常 2.2 第二次通过调用setVisibil ...

  8. android 设备驱动 位置,android中各个部件驱动在源码中的位置

    Android的专用驱动:Ashmem.binder.logger Ashmem:匿名共享内存驱动 Logger:轻量级的log驱动 Binder:基于OpenBinder驱动,为android平台提 ...

  9. Android中相机(Camera)画面旋转角度分析:手机摄像头的“正向”、手机画面自然方向、相机画面的偏转角度

    #.概述: 1.如同人眼看东西分上下一样,摄像头也有其"正向",正常情况下,Android手机后置.前置摄像头的"正向"朝向为手机的"右侧" ...

最新文章

  1. 从 Kafka 看时间轮算法设计
  2. Java实用教程 课堂测试(2021C++补考题目)
  3. 现代操作系统:进程和线程总结
  4. winCE下Unicode编码
  5. t3显示乱码_打开T3出现乱码是什么原因,如下图
  6. python ssl socket_Python使用Socket(Https)Post登录百度的实现代码
  7. 02_HBase集群部署
  8. Android程序开发:简单电话拨号器
  9. 爱的十个秘密--8.沟通的力量
  10. matlab肆,matlab入门教程
  11. OpenG 编程指南英文整理
  12. boost电路输出电流公式_Boost电路的参数计算及仿真
  13. 数学知识学习之——商空间(Quotient Spaces)
  14. chrome 打包安装插件
  15. 26.看前端视频的感悟,来自碎碎念记录
  16. 社会兼职工作实践报告
  17. java下载图片到本地,例如从网上下载图片,下载淘宝图片,下载百度图片等
  18. DeepLab系列总结
  19. BSV 上的 Schnorr 签名
  20. Java内存区域和GC机制

热门文章

  1. jsb.reflection.callStaticMethod
  2. python 手动清除内存gc
  3. 小程序---wxParse解决图片大小不适应小程序页面问题
  4. ilo4服务器远程,HP服务器ilo远程管理端口设置
  5. 二类医疗器械定义及分类
  6. 软件测试的概念及详细分类的介绍
  7. 如何用HTML制作一个房子,一分钟,教会你农村自建房该怎么设计!小白学了都能上手画出设计图!...
  8. HDU4417 Super Mario (主席树模板)
  9. Ubuntu安装Kinect驱动(openni、NITE、Sensor)及遇到的问题
  10. MySQL Java JDBC