Android LCD和键盘 背光亮度数据流分析

18 篇文章 2 订阅
16 篇文章 4 订阅
同时参考:linux设备模型之led子系统

1【从应用层到Framework】android LCD、键盘灯的背光亮度设置 

2   原文地址:  http://www.linuxidc.com/Linux/2011-03/33311p2.htm


 

 

亮度设置
应用设计
1.1 设置进度条范围
背光设置是在:设置->声音和显示->亮度,通过进度条来设置的。

文件:
packages/apps/Settings/src/com/Android/settings/BrightnessPreference.java

Java代码 复制代码   收藏代码
  1. private static final int MINIMUM_BACKLIGHT = Android.os.Power.BRIGHTNESS_DIM 10;   
  2. private static final int MAXIMUM_BACKLIGHT = Android.os.Power.BRIGHTNESS_ON;     
  3. mSeekBar.setMax(MAXIMUM_BACKLIGHT - MINIMUM_BACKLIGHT);  


设置进度条的范围,BRIGHTNESS_DIM = 20  BRIGHTNESS_ON=255,它们的定义在:
frameworks/base/core/java/Android/os/Power.java
1.2 设置亮度
文件:packages/apps/Settings/src/com/Android/settings/BrightnessPreference.java

Java代码 复制代码   收藏代码
  1. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {     
  2.        setMode(isChecked ? Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC     
  3.                 : Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);     
  4.         if (!isChecked) {     
  5.             setBrightness(mSeekBar.getProgress() + MINIMUM_BACKLIGHT);     
  6.         }     
  7.     }   
  8.   
  9. private void setBrightness(int brightness) {     
  10.         try {     
  11.             IPowerManager power = IPowerManager.Stub.asInterface(     
  12.                     ServiceManager.getService("power"));    
  13.             if (power != null) {     
  14.                 power.setBacklightBrightness(brightness);     
  15.             }   
  16.         } catch (RemoteException doe) {   
  17.         }          
  18. }  


由以上代码可知,brightness的范围是:20~255;代码通过服务管理器(ServiceManager)获得power服务,然后通过power服务设置亮度。
power.setBacklightBrightness的定义在:
rameworks/base/core/java/Android/os/IPowerManager.aidl.java
frameworks/base/core/java/Android/os/PowerManager.java

2, Power服务
文件:frameworks/base/core/java/Android/os/Power.java

                  /** * Brightness value for dim backlight   */ 
    public static final int BRIGHTNESS_DIM = 20; 
                  /** * Brightness value for fully on      */ 

    public static final int BRIGHTNESS_ON = 255; 

文件:frameworks/base/core/java/Android/os/PowerManager.java
Java代码 复制代码 收藏代码

  1. /** * sets the brightness of the backlights (screen, keyboard, button). 
  2.       *   
  3.      * @param brightness value from 0 to 255   
  4.      *   
  5.      * {@hide}  
  6.      */  
  7.   
  8.     public void setBacklightBrightness(int brightness)     
  9.     {     
  10.         try {     
  11.             mService.setBacklightBrightness(brightness);     
  12.         } catch (RemoteException e) {   
  13.            }   
  14. }  

新代码起始:

framework\base\service\java\com\android\server\PowerManagerService.java
 
//PowerManagerService中定义的mButtonLight和mKeyboardLight都是键盘灯,具体使用哪一个,要看底层的平台厂商使用
0196	    private LightsService.Light mLcdLight;
0197	    private LightsService.Light mButtonLight;
0198	    private LightsService.Light mKeyboardLight;
 
2921	    public void setBacklightBrightness(int brightness) {
2922	        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
2923	        // Don't let applications turn the screen all the way off
2924	        synchronized (mLocks) {
2925	            brightness = Math.max(brightness, mScreenBrightnessDim);
                    //以下设备分别调用了LightsService.light的接口
2926	            mLcdLight.setBrightness(brightness);
2927	            mKeyboardLight.setBrightness(mKeyboardVisible ? brightness : 0);
2928	            mButtonLight.setBrightness(brightness);
2929	            long identity = Binder.clearCallingIdentity();
2930	            try {
2931	                mBatteryStats.noteScreenBrightness(brightness);
2932	            } catch (RemoteException e) {
2933	                Slog.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);
2934	            } finally {
2935	                Binder.restoreCallingIdentity(identity);
2936	            }
2937	  
2938	            // update our animation state
2939	            synchronized (mLocks) {
2940	                mScreenBrightness.targetValue = brightness;
2941	                mScreenBrightness.jumpToTargetLocked();
2942	            }
2943	        }
2944	    }
 
framework\base\service\java\com\android\server\LightsService.java
 
066	        public void setBrightness(int brightness) {
067	            setBrightness(brightness, BRIGHTNESS_MODE_USER);
068	        }
069	  
070	        public void setBrightness(int brightness, int brightnessMode) {
071	            synchronized (this) {
072	                int color = brightness & 0x000000ff;
073	                color = 0xff000000 | (color << 16) | (color << 8) | color;
074	                setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
075	            }
076	        }
 
116	        private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
117	            if (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS) {
118	                mColor = color;
119	                mMode = mode;
120	                mOnMS = onMS;
121	                mOffMS = offMS;
                        //调用JNI的本地接口,mNativePointer对应具体设备,通过调用LighsService中的init接口,进一步调用init_native接口获取设备信息
122	                setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);
123	            }
124	        }
 
framework\base\services\jni\com_android_server_LightsService.cpp
  
106	static void setLight_native(JNIEnv *env, jobject clazz, int ptr,
107	        int light, int colorARGB, int flashMode, int onMS, int offMS, int brightnessMode)
108	{
109	    Devices* devices = (Devices*)ptr;
110	    light_state_t state;
111	  
112	    if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {
113	        return ;
114	    }
115	  
116	    memset(&state, 0, sizeof(light_state_t));
117	    state.color = colorARGB;
118	    state.flashMode = flashMode;
119	    state.flashOnMS = onMS;
120	    state.flashOffMS = offMS;
121	    state.brightnessMode = brightnessMode;
122	  
         //devices->lights是一个结构体,具体定义没找到,不过根据代码看,set_light应该是一个函数指针这里会根据不同的设备devices调用对应的set_light指向的具体函数
123	    devices->lights[light]->set_light(devices->lights[light], &state);
124	}

新代码截止


旧代码起始:

电源管理器(powermager)将brightness转给电源服务,该服务位置如下:

文件:frameworks/base/services/java/com/Android/server/PowerManagerService.java

Java代码 复制代码  收藏代码
  1. public void setBacklightBrightness(int brightness) {     
  2.         mContext.enforceCallingOrSelfPermission(Android.Manifest.permission.DEVICE_POWER, null);     
  3.         // Don't let applications turn the screen all the way off    
  4.         brightness = Math.max(brightness, Power.BRIGHTNESS_DIM);     
  5.         mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT, brightness, HardwareService.BRIGHTNESS_MODE_USER);     
  6.         mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, (mKeyboardVisible ? brightness : 0), HardwareService.BRIGHTNESS_MODE_USER);     
  7.         mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, brightness, HardwareService.BRIGHTNESS_MODE_USER);     
  8.         long identity = Binder.clearCallingIdentity();     
  9.         try {     
  10.             mBatteryStats.noteScreenBrightness(brightness);     
  11.         } catch (RemoteException e) {    
  12.             Log.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);     
  13.         } finally {     
  14.             Binder.restoreCallingIdentity(identity);     
  15.         }   
  16.   
  17.         // update our animation state   
  18.   
  19.         if (ANIMATE_SCREEN_LIGHTS) {     
  20.             mScreenBrightness.curValue = brightness;    
  21.             mScreenBrightness.animating = false;     
  22.             mScreenBrightness.targetValue = -1;     
  23.         }   
  24.   
  25.         if (ANIMATE_KEYBOARD_LIGHTS) {     
  26.             mKeyboardBrightness.curValue = brightness;     
  27.             mKeyboardBrightness.animating = false;   
  28.               mKeyboardBrightness.targetValue = -1;     
  29.         }   
  30.   
  31.         if (ANIMATE_BUTTON_LIGHTS) {   
  32.   
  33.             mButtonBrightness.curValue = brightness;     
  34.             mButtonBrightness.animating = false;     
  35.             mButtonBrightness.targetValue = -1;     
  36.         }     
  37.     }  
由以上代码可知, 同时设置了背光、键盘、按钮的亮度mHardware是硬件服务,通过该服务调用底层与设备打交道的C\C++代码setLightBrightness_UNCHECKED原型如下:
文件:frameworks/base/services\java\com\Android\server\HardwareService.java
Java代码 复制代码  收藏代码
  1. void setLightBrightness_UNCHECKED(int lightint brightnessint brightnessMode) {   
  2.                                                                                类型         亮度值                控制模式 
  3.         int b = brightness & 0x000000ff;     
  4.         b = 0xff000000 | (b << 16) | (b << 8) | b;     
  5.         setLight_native(mNativePointer, light, b, LIGHT_FLASH_NONE00, brightnessMode);     
  6.      //  函数参见3.2  
  7.     }  

参数说明:

int light 表示类型,选项如下:

    static final int LIGHT_ID_BACKLIGHT = 0; 

    static final int LIGHT_ID_KEYBOARD = 1;
    static final int LIGHT_ID_BUTTONS = 2;
    static final int LIGHT_ID_BATTERY = 3;
    static final int LIGHT_ID_NOTIFICATIONS = 4;
    static final int LIGHT_ID_ATTENTION = 5;
int brightness 表示亮度值
int brightnessMode 表示亮度的控制模式,选项如下: 
   static final int BRIGHTNESS_MODE_USER = 0;                  /** * Light brightness is managed by a user setting.      */
   static final int BRIGHTNESS_MODE_SENSOR = 1;             /*** Light brightness is managed by a light sensor.        */


由代码: 
        int b = brightness & 0x000000ff;
        b = 0xff000000 | (b << 16) | (b <<8 | b;
可知,亮度值在此进行了修改,即亮度值的格式变成:FFRRGGBB,FF是没有的,RR、GG、BB分别是256色的红绿蓝,并且红绿蓝的值都是一样的亮度值。


 

旧代码截止

 

3 硬件调用
3.1获取硬件
新代码:在文件:frameworks/base/services/jni/com_Android_server_LightService.cpp

旧代码:文件:frameworks/base/services/jni/com_Android_server_HardwareService.cpp

Cpp代码 复制代码  收藏代码
  1. enum {     
  2.     LIGHT_INDEX_BACKLIGHT = 0,     
  3.     LIGHT_INDEX_KEYBOARD = 1,     
  4.     LIGHT_INDEX_BUTTONS = 2,     
  5.     LIGHT_INDEX_BATTERY = 3,     
  6.     LIGHT_INDEX_NOTIFICATIONS = 4,     
  7.     LIGHT_INDEX_ATTENTION = 5,     
  8.     LIGHT_COUNT     
  9. };   
  10.   
  11. #define LIGHTS_HARDWARE_MODULE_ID "lights"  
  12.   
  13. static jint init_native(JNIEnv *env, jobject clazz)     
  14. {   
  15.     int err;     
  16.     hw_module_t* module;     
  17.     Devices* devices;       
  18.   
  19.     devices = (Devices*)malloc(sizeof(Devices));     
  20.     err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);     
  21.     if (err == 0) {   
  22.         devices->lights[LIGHT_INDEX_BACKLIGHT]                   = get_device(module, LIGHT_ID_BACKLIGHT);     
  23.         devices->lights[LIGHT_INDEX_KEYBOARD]                    = get_device(module, LIGHT_ID_KEYBOARD);     
  24.         devices->lights[LIGHT_INDEX_BUTTONS]                       = get_device(module, LIGHT_ID_BUTTONS);     
  25.         devices->lights[LIGHT_INDEX_BATTERY]                        = get_device(module, LIGHT_ID_BATTERY);     
  26.         devices->lights[LIGHT_INDEX_NOTIFICATIONS]            = get_device(module, LIGHT_ID_NOTIFICATIONS);     
  27.         devices->lights[LIGHT_INDEX_ATTENTION]                    = get_device(module, LIGHT_ID_ATTENTION);     
  28.     } else {   
  29.           memset(devices, 0, sizeof(Devices));     
  30.     }   
  31.      return (jint)devices;     
  32. }  
hw_get_module获取ID为LIGHTS_HARDWARE_MODULE_ID的硬件模块,该模块含有6个不同类型的亮度控制。
hw_get_module 的实现原理,如下:
文件:hardware/libhardware/Hardware.c
C代码 复制代码  收藏代码
  1. #define HAL_LIBRARY_PATH "/system/lib/hw"  
  2.   
  3. static const char *variant_keys[ ] = {     
  4.     "ro.hardware",                /* This goes first so that it can pick up a different  file on the emulator. */                      
  5.      "ro.product.board",     
  6.     "ro.board.platform",     
  7.     "ro.arch"   
  8. };   
  9.   
  10. static const int HAL_VARIANT_KEYS_COUNT =    (sizeof(variant_keys)/sizeof(variant_keys[0]));    
  11.   
  12. int hw_get_module(const char *id, const struct hw_module_t **module)     
  13. {   int status;   
  14.     int i;     
  15.     const struct hw_module_t *hmi = NULL;     
  16.     char prop[PATH_MAX];     
  17.     char path[PATH_MAX];     
  18.     /* Here we rely on the fact that calling dlopen multiple times on   the same .so will simply increment a refcount (and not load  
  19.      * a new copy of the library).   We also assume that dlopen() is thread-safe.  
  20.      */  
  21.       /* Loop through the configuration variants looking for a module */  
  22.   
  23.     for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {     
  24.         if (i < HAL_VARIANT_KEYS_COUNT) {     
  25.             if (property_get(variant_keys[i], prop, NULL) == 0) {     
  26.                 continue;     
  27.             }   
  28.   
  29.             snprintf(pathsizeof(path), "%s/%s.%s.so", HAL_LIBRARY_PATH, id, prop);     
  30.         } 
  31.        else {     
  32.             snprintf(path, sizeof(path), "%s/%s.default.so",  HAL_LIBRARY_PATH, id);     
  33.         }     
  34.         if (access(path, R_OK)) {     
  35.             continue;     
  36.         }     
  37.         /* we found a library matching this id/variant */    
  38.         break;   
  39.       }   
  40.   
  41.     status = -ENOENT;     
  42.     if (i < HAL_VARIANT_KEYS_COUNT+1) {     
  43.         /* load the module, if this fails, we're doomed, and we should not try  to load a different variant. */    
  44.         status = load(id, path, module);     
  45.     }   
  46.      return status;   
  47.   }  

property_get(variant_keys[i], prop, NULL) 会按如下顺序去获取如下变量所对应的值,然后返回给prop
"ro.hardware",  

 "ro.product.board",
 "ro.board.platform",
 "ro.arch"

它们对应的变量为:
"ro.product.board=$TARGET_BOOTLOADER_BOARD_NAME"
"ro.board.platform=$TARGET_BOARD_PLATFORM"

如vendor/htc/dream-open/BoardConfig.mk里定义的TARGET_BOARD_PLATFORM := msm7k,则prop返回"msm7k ”,所以path= /system/lib/hw/lights. msm7k.so,也就是说要获取的硬件模块为lights. msm7k.so。

3.2调用硬件

setLight_native对应的jni C/C++代码是:
文件:frameworks/base/services/jni/com_Android_server_HardwareService.cpp

Cpp代码 复制代码  收藏代码
  1. static void setLight_native(JNIEnv *env, jobject clazz, int ptr, int light, int colorARGB, int flashMode, int onMS, int offMS, int brightnessMode)
  2. {  
  3.     Devices* devices = (Devices*)ptr;     
  4.     light_state_t state;     
  5.     if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {     
  6.         return ;     
  7.     }   
  8.     memset(&state, 0, sizeof(light_state_t));   
  9.     state.color = colorARGB;     
  10.     state.flashMode = flashMode;     
  11.     state.flashOnMS = onMS;     
  12.     state.flashOffMS = offMS;     
  13.     state.brightnessMode = brightnessMode;     
  14.     devices->lights[light]->set_light(devices->lights[light], &state);     
  15. }  
通过 light标识找到对应的light设备,然后再设置亮度。

3.3 硬件原型
msm7k的lights对应的硬件原型是在:hardware/msm7k/liblights
文件:hardware/msm7k/liblights/Android.mk
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw 
LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM) 
也就是生成模块:/system/lib/hw/lights. msm7k.so

文件:hardware/msm7k/liblights/lights.c
C代码 复制代码  收藏代码
  1. /** Open a new instance of a lights device using name */    
  2. static int open_lights(const struct hw_module_t* module, char const* name,     
  3.         struct hw_device_t** device)     
  4. {     
  5.     int (*set_light)(struct light_device_t* dev,   struct light_state_t const* state);                 
  6.   
  7.     if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) {     
  8.         set_light = set_light_backlight;     
  9.        }    
  10.  
  11.     else if (0 == strcmp(LIGHT_ID_KEYBOARD, name)) {     
  12.         set_light = set_light_keyboard;     
  13.     }     
  14.     else if (0 == strcmp(LIGHT_ID_BUTTONS, name)) {     
  15.         set_light = set_light_buttons;     
  16.     }     
  17.     else if (0 == strcmp(LIGHT_ID_BATTERY, name)) {     
  18.         set_light = set_light_battery;     
  19.     }     
  20.     else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) {     
  21.         set_light = set_light_notifications;     
  22.     }     
  23.     else if (0 == strcmp(LIGHT_ID_ATTENTION, name)) {     
  24.         set_light = set_light_attention;     
  25.     }   
  26.   
  27.     else {     
  28.         return -EINVAL;     
  29.     }   
  30.   
  31.     pthread_once(&g_init, init_globals);     
  32.     struct light_device_t *dev = malloc(sizeof(struct light_device_t));     
  33.     memset(dev, 0, sizeof(*dev));     
  34.     dev->common.tag = HARDWARE_DEVICE_TAG;     
  35.     dev->common.version = 0;     
  36.     dev->common.module = (struct hw_module_t*)module;     
  37.     dev->common.close = (int (*)(struct hw_device_t*))close_lights;     
  38.     dev->set_light = set_light;     
  39.     *device = (struct hw_device_t*)dev;     
  40.     return 0;     
  41. }   
  42.   
  43. static struct hw_module_methods_t lights_module_methods = {     
  44.     .open =  open_lights,     
  45. };  
以上代码对应的是:
        devices->lights[LIGHT_INDEX_BACKLIGHT]     = get_device(module, LIGHT_ID_BACKLIGHT);
        devices->lights[LIGHT_INDEX_KEYBOARD]         = get_device(module, LIGHT_ID_KEYBOARD);
        devices->lights[LIGHT_INDEX_BUTTONS]             = get_device(module, LIGHT_ID_BUTTONS);
        devices->lights[LIGHT_INDEX_BATTERY]             = get_device(module, LIGHT_ID_BATTERY);
        devices->lights[LIGHT_INDEX_NOTIFICATIONS] = get_device(module, LIGHT_ID_NOTIFICATIONS);
        devices->lights[LIGHT_INDEX_ATTENTION]         = get_device(module, LIGHT_ID_ATTENTION);

也就是说,对不同的亮度设置给予了不同的设置函数。
举例,背光设置,背光对应的代码如下:

char const*const LCD_FILE         = "/sys/class/leds/lcd-backlight/brightness";
static int  rgb_to_brightness(struct light_state_t const* state) 
{ 
    int color = state->color & 0x00ffffff; 
    return ((77*((color>>16)&0x00ff))  + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
} 

static int set_light_backlight(struct light_device_t* dev,      struct light_state_t const* state)
{ 
    int err = 0; 
    int brightness = rgb_to_brightness(state); 
    pthread_mutex_lock(&g_lock); 
    g_backlight = brightness; 
    err = write_int(LCD_FILE, brightness); 
    if (g_haveTrackballLight) { 
        handle_trackball_light_locked(dev); 
    } 

    pthread_mutex_unlock(&g_lock); 
    return err; 
} 
也就是 往文件/sys/class/leds/lcd-backlight/brightness写入亮度值,然后驱动会根据该文件更改背光的亮度。LCD_FILE的路径根据实际情况更改,同时需要在init.rc 修改其权限,使其可写rgb_to_brightness也根据实际更改,比如要直接亮度值控制,那只要获取r,g,b其中的一个值就行了,如:
static int rgb_to_brightness(struct light_state_t const* state) 
{ 
    int color = state->color & 0x000000ff; 
    return color; 
} 

4,led类驱动

4.1,驱动创建leds类,系统启动时执行leds_init在目录/sys/class/创建子目录leds
kernel\drivers\leds\Led-class.c
C代码 复制代码  收藏代码
  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;                                                //属性文件,sys下的接口,重点看一下
  9.  return 0;   
  10. }  

4.2,led_classdev_register,调用这个函数就在目录/sys/class/leds创建子目录led_cdev->name和属性文件brightness
brightness文件写就执行led_brightness_store,对brightness文件读就执行led_brightness_show,为下面的lcd,led注册做好准备
因为:

kernel\drivers\leds\Led-class.c
C代码 复制代码 收藏代码

  1. static ssize_t led_brightness_show(struct device *dev,    
  2.   struct device_attribute *attr, char *buf)   
  3. {   
  4.  struct led_classdev *led_cdev = dev_get_drvdata(dev);     
  5.  /* no lock needed for this */  
  6.  led_update_brightness(led_cdev);     
  7.  return sprintf(buf, "%u\n", led_cdev->brightness);   
  8. }   
  9.   
  10. static ssize_t led_brightness_store(struct device *dev,   
  11.   struct device_attribute *attr, const char *buf, size_t size)   
  12. {   
  13.  struct led_classdev *led_cdev = dev_get_drvdata(dev);   
  14.  ssize_t ret = -EINVAL;   
  15.  char *after;   
  16.  unsigned long state = simple_strtoul(buf, &after, 10);   
  17.  size_t count = after - buf;   
  18.   
  19.  if (*after && isspace(*after))   
  20.   count++;   
  21.   
  22.  if (count == size) {   
  23.   ret = count;     
  24.   if (state == LED_OFF)   
  25.    led_trigger_remove(led_cdev);   
  26.   led_set_brightness(led_cdev, state);   
  27.  }     
  28.  return ret;   
  29. }   
  30. 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);
    }
  31.   
  32. static struct device_attribute led_class_attrs[] = {
     __ATTR(brightness, 0644, led_brightness_store, led_brightness_store),
     __ATTR(max_brightness, 0644, led_max_brightness_show,led_max_brightness_store),
    #ifdef CONFIG_LEDS_TRIGGERS
     __ATTR(trigger, 0644, led_trigger_show, led_trigger_store),
    #endif
     __ATTR_NULL,
    };
    /* led_classdev_register - register a new object of led_classdev class. 
  33.  * @parent: The device to register. 
  34.  * @led_cdev: the led_classdev structure for this device. 
  35.  */  
  36. int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)   
  37. {   
  38.            int rc;     
  39.            led_cdev->dev = device_create(leds_class, parent, 0, led_cdev,    "%s", led_cdev->name);   
  40.            if (IS_ERR(led_cdev->dev))   
  41.           return PTR_ERR(led_cdev->dev);     
  42.  /* register the attributes */  
  43.           rc = device_create_file(led_cdev->dev, &dev_attr_brightness);   
  44.           if (rc)   
  45.                   goto err_out;   
  46.   
  47. #ifdef CONFIG_LEDS_TRIGGERS   
  48.            init_rwsem(&led_cdev->trigger_lock);   
  49. #endif   
  50.  /* add to the list of leds */  
  51.            down_write(&leds_list_lock);   
  52.            list_add_tail(&led_cdev->node, &leds_list);   
  53.            up_write(&leds_list_lock);   
  54.   
  55.             led_update_brightness(led_cdev);   
  56.   
  57. #ifdef CONFIG_LEDS_TRIGGERS   
  58.           rc = device_create_file(led_cdev->dev, &dev_attr_trigger);   
  59.           if (rc)   
  60.                 goto err_out_led_list;   
  61.           led_trigger_set_default(led_cdev);   
  62. #endif     
  63.           printk(KERN_INFO "Registered led device: %s\n",   led_cdev->name);     
  64.           return 0;   
  65.   
  66. #ifdef CONFIG_LEDS_TRIGGERS   
  67.            err_out_led_list:   
  68.            device_remove_file(led_cdev->dev, &dev_attr_brightness);   
  69.            list_del(&led_cdev->node);   
  70. #endif   
  71. err_out:   
  72.             device_unregister(led_cdev->dev);   
  73.             return rc;   
  74. }   
  75. EXPORT_SYMBOL_GPL(led_classdev_register);  
4.3,lcd驱动 调用led_classdev_register,在目录/sys/class/leds创建子目录lcd- backlight和属性文件brightness

kernel\drivers\video\msm\Msm_fb.c
C代码 复制代码  收藏代码
  1. static int lcd_backlight_registered;     
  2. static void msm_fb_set_bl_brightness(struct led_classdev *led_cdev, enum led_brightness value)       
  3. {   
  4.  struct msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent);   
  5.  int bl_lvl;   
  6.   
  7.  if (value > MAX_BACKLIGHT_BRIGHTNESS)   
  8.   value = MAX_BACKLIGHT_BRIGHTNESS;   
  9.   
  10.  /* This maps Android backlight level 0 to 255 into 
  11.     driver backlight level 0 to bl_max with rounding */  
  12.  bl_lvl = (2 * value * mfd->panel_info.bl_max + MAX_BACKLIGHT_BRIGHTNESS)  /(2 * MAX_BACKLIGHT_BRIGHTNESS);   
  13.   
  14.  if (!bl_lvl && value)     bl_lvl = 1;     
  15.  msm_fb_set_backlight(mfd, bl_lvl, 1);   
  16. }   
  17.   
  18. static struct led_classdev backlight_led = {   
  19.  .name  = "lcd-backlight",   
  20.  .brightness = MAX_BACKLIGHT_BRIGHTNESS,   
  21.  .brightness_set = msm_fb_set_bl_brightness,   
  22. };   
  23.   
  24.  if (!lcd_backlight_registered) {   
  25.   if (led_classdev_register(&pdev->dev, &backlight_led))   
  26.    printk(KERN_ERR "led_classdev_register failed\n");   
  27.   else  
  28.    lcd_backlight_registered = 1;   
  29.  }  

就在目录/sys/class/leds创建子目录 lcd-backlight和属性文件brightness
当按键或者来的或者改变lcd亮度时,上层对属性文件/sys/class/leds/lcd-backlight/brightness写入背光的亮度数值就
调用led_brightness_store >>调用simple_strtoul(buf, &after, 10);将输入的字符串转换为10进制的数字

然后接着执行led_set_brightness ,内部会调用执行led_cdev->brightness_set(led_cdev, value),也就是调用》msm_fb_set_bl_brightness ,

因为  .brightness_set = msm_fb_set_bl_brightness,

msm_fb_set_bl_brightness函数里面代码:
/* This maps Android backlight level 0 to 255 into    driver backlight level 0 to bl_max with rounding */
bl_lvl = (2 * value * mfd->panel_info.bl_max + MAX_BACKLIGHT_BRIGHTNESS)  /(2 * MAX_BACKLIGHT_BRIGHTNESS);
将输入的0--255转换为IC的0--bl_max

msm_fb_set_bl_brightness 里面同时还调用 msm_fb_set_backlight(mfd, bl_lvl, 1);

其代码如下:
void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl)
{ struct msm_fb_panel_data *pdata;
  if (!mfd->panel_power_on || !bl_updated) {
  unset_bl_level = bkl_lvl;
  return;
  } else {
       unset_bl_level = 0;
  }
  pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;

  if ((pdata) && (pdata->set_backlight)) {
      down(&mfd->sem);
      if (bl_level_old == bkl_lvl) {
      up(&mfd->sem);
      return;
  }

    mfd->bl_level = bkl_lvl;     // mdf->bl_level在具体的lcd驱动文件中的xxx_set_backlight()函数中会调用
    pdata->set_backlight(mfd);   //调用xxx_set_backlight()函数
    bl_level_old = mfd->bl_level;
    up(&mfd->sem);        
    }
}
最终改变LCD的背光驱动电路的设置,调节LCD的背光的亮度

4.4 键盘背光灯

上层对属性文件/sys/class/leds/keyboard-backlight/brightness写入背光的亮度数值
(kernel\drivers\leds\Leds-msm-pmic.c

C代码 复制代码  收藏代码
  1. #define MAX_KEYPAD_BL_LEVEL 16   
  2.   
  3. static void msm_keypad_bl_led_set(struct led_classdev *led_cdev,   
  4.  enum led_brightness value)   
  5. {   
  6.             int ret;     
  7.             ret = pmic_set_led_intensity(LED_KEYPAD, value / MAX_KEYPAD_BL_LEVEL);   
  8.            if (ret)   
  9.             dev_err(led_cdev->dev, "can't set keypad backlight\n");   
  10. }   
  11.   
  12. static struct led_classdev msm_kp_bl_led = {   
  13.       .name   = "keyboard-backlight",   
  14.       .brightness_set  = msm_keypad_bl_led_set,   
  15.       .brightness  = LED_OFF,   
  16. };   
  17.   
  18. static int msm_pmic_led_probe(struct platform_device *pdev)   
  19. {   
  20.            int rc;   
  21.   
  22.            rc = led_classdev_register(&pdev->dev, &msm_kp_bl_led);   
  23.            if (rc) {   
  24.                     dev_err(&pdev->dev, "unable to register led class driver\n");   
  25.                     return rc;   
  26.            }   
  27.           msm_keypad_bl_led_set(&msm_kp_bl_led, LED_OFF);   
  28.           return rc;   
  29. }   
  30.   
  31. static int __devexit msm_pmic_led_remove(struct platform_device *pdev)   
  32. {   
  33.      led_classdev_unregister(&msm_kp_bl_led);     
  34.      return 0;   
  35. }   
  36.   
  37. #ifdef CONFIG_PM   
  38. static int msm_pmic_led_suspend(struct platform_device *dev,     pm_message_t state)   
  39. {   
  40.     led_classdev_suspend(&msm_kp_bl_led);     
  41.     return 0;   
  42. }   
  43.   
  44. static int msm_pmic_led_resume(struct platform_device *dev)   
  45. {   
  46.         led_classdev_resume(&msm_kp_bl_led);     
  47.          return 0;   
  48. }   
  49. #else   
  50. #define msm_pmic_led_suspend NULL   
  51. #define msm_pmic_led_resume NULL   
  52. #endif   
  53.   
  54. static struct platform_driver msm_pmic_led_driver = {   
  55.  .probe  = msm_pmic_led_probe,   
  56.  .remove  = __devexit_p(msm_pmic_led_remove),   
  57.  .suspend = msm_pmic_led_suspend,   
  58.  .resume  = msm_pmic_led_resume,   
  59.  .driver  = {   
  60.   .name = "pmic-leds",   
  61.   .owner = THIS_MODULE,   
  62.  },   
  63. };   
  64.   
  65. static int __init msm_pmic_led_init(void)   
  66. {   
  67.           return platform_driver_register(&msm_pmic_led_driver);   
  68. }   
  69. module_init(msm_pmic_led_init);   
  70.   
  71. static void __exit msm_pmic_led_exit(void)   
  72. {   
  73.           platform_driver_unregister(&msm_pmic_led_driver);   
  74. }   
  75. module_exit(msm_pmic_led_exit);  

MODULE_DESCRIPTION("MSM PMIC LEDs driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:p

系统行动执行msm_pmic_led_init(void) ,实质是调用》 platform_driver_register(&msm_pmic_led_driver);
接着调用msm_pmic_led_probe ,完成调用 led_classdev_register(&pdev->dev, &msm_kp_bl_led);

就在目录/sys/class/leds创建子目录 keyboard-backlight和属性文件brightness
当按键时,上层对属性文件/sys/class/leds/keyboard-backlight/brightness写入背光的亮度数值就
调用led_brightness_store ,从而调用simple_strtoul(buf, &after, 10);将输入的字符串转换为10进制的数字
然后执行led_set_brightness,》》》》执行led_cdev->brightness_set(led_cdev, value
调用msm_keypad_bl_led_set ,因为 .brightness_set  =msm_keypad_bl_led_set,
调用 ret = pmic_set_led_intensity(LED_KEYPAD, value / MAX_KEYPAD_BL_LEVEL);
最终改变LED驱动电路的设置,调节LED的亮度

 

参考另外另外两文章总结:

 

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值