android 系统(20)---背光灯


图1

这是MTK 2011年的图,下面给出MT6575/6577中此部分的框架图:


图2

再来看更体现一些细节的框架图:


图3

由此可见光系统从上到下依次分为java APP层、java 框架层、本地层和驱动层。下面就来看APP层,先给出调节背光的应用界面:


图4

此功能在settings--->display--->brightness下面,可知有自动调节和手动调节背光亮度的功能,其中手动是通过进度条(slider)来调节的,此应用对应的布局文件为\packages\apps\Settings\res\layout\preference_dialog_brightness.xml

 

1.     Lights应用层

1.1   设置背光亮度调节范围

 

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. \packages\apps\Settings\src\com\android\settings\BrightnessPreference.java  
  2.    
  3.   // Backlight range is from 0 - 255. Need tomake sure that user  
  4.     // doesn't set the backlight to 0 and getstuck  
  5.     private int mScreenBrightnessDim =  
  6.                  getContext().getResources().getInteger(com.android.internal.R.integer.config_screenBrightnessDim);  
  7. private staticfinal int MAXIMUM_BACKLIGHT = android.os.Power.BRIGHTNESS_ON;  
  8.    
  9.     @Override  
  10.     protected void onBindDialogView(View view){  
  11.         super.onBindDialogView(view);  
  12.    
  13.         mSeekBar = getSeekBar(view);  
  14.         mSeekBar.setMax(MAXIMUM_BACKLIGHT -mScreenBrightnessDim);  
  15.         mOldBrightness = getBrightness(0);  
  16.         mSeekBar.setProgress(mOldBrightness -mScreenBrightnessDim);  
  17.    
  18.         mCheckBox =(CheckBox)view.findViewById(R.id.automatic_mode);  
  19.         if (mAutomaticAvailable) {  
  20.             mCheckBox.setOnCheckedChangeListener(this);  
  21.             mOldAutomatic =getBrightnessMode(0);  
  22.             mCheckBox.setChecked(mOldAutomatic!= 0);  
  23.         } else {  
  24.             mCheckBox.setVisibility(View.GONE);  
  25.         }  
  26.        mSeekBar.setOnSeekBarChangeListener(this);  
  27. }  

(1)         getContext().getResources().getInteger(com.android.internal.R.integer.config_screenBrightnessDim)的值

在\frameworks\base\core\res\res\values\config.xml下赋值,如下:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <!-- Minimumscreen brightness allowed by the power manager. -->  
  2. <integernameintegername="config_screenBrightnessDim">20</integer>  

可见背光亮度最小值是20,不能设置为0,否则会关闭背光的显示。

 

(2)          android.os.Power.BRIGHTNESS_ON的值

在\frameworks\base\core\java\android\os\Power.java中定义:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.      * Brightness value for fully off 
  3.      */  
  4.     public static final int BRIGHTNESS_OFF = 0;  
  5.    
  6.     /** 
  7.      * Brightness value for dim backlight 
  8.      */  
  9.     public static final int BRIGHTNESS_DIM =20;  
  10.    
  11.     /** 
  12.      * Brightness value for fully on 
  13.      */  
  14.     public static final int BRIGHTNESS_ON =255;  
  15.    
  16.     /** 
  17.      * Brightness value to use when battery islow 
  18.      */  
  19. public staticfinal int BRIGHTNESS_LOW_BATTERY = 10;  


由此可见设置的背光亮度调节范围为20~255。

 

1.2   设置背光亮度

 

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public voidonProgressChanged(SeekBar seekBar, int progress,  
  2.             boolean fromTouch) {  
  3.         setBrightness(progress +mScreenBrightnessDim);  
  4. }  
  5. progress表示滑动条的值。  
  6.    
  7.   private void setBrightness(int brightness) {  
  8.         try {  
  9.             IPowerManager power =IPowerManager.Stub.asInterface(  
  10.                    ServiceManager.getService("power"));  
  11.             //Only set backlight value whenscreen is on  
  12.             if (power != null &&power.isScreenOn()) {  
  13.                 power.setBacklightBrightness(brightness);  
  14.             }  
  15.         } catch (RemoteException doe) {  
  16.              
  17.         }  
  18. }  

通过ServiceManager获得power服务,然后通过power服务设置背光亮度

 

1.3   背光亮度初始值

frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\DatabaseHelper.java

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private voidloadSystemSettings(SQLiteDatabase db) {  
  2.       SQLiteStatement stmt = null;  
  3.       try {  
  4.                                         ……….  
  5.                                         loadIntegerSetting(stmt,Settings.System.SCREEN_BRIGHTNESS,  
  6.                  R.integer.def_screen_brightness);  
  7.    
  8.          loadBooleanSetting(stmt,Settings.System.SCREEN_BRIGHTNESS_MODE,  
  9.                  R.bool.def_screen_brightness_automatic_mode);  
  10.                                         ……………..  
  11.      } finally {  
  12.           if (stmt != null) stmt.close();  
  13.       }  
  14.   }  

def_screen_brightness的值在下面定义:

\frameworks\base\packages\SettingsProvider\res\values\ defaults.xml

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <integernameintegername="def_screen_brightness">102</integer>  
  2. <boolnameboolname="def_screen_brightness_automatic_mode">false</bool>  

可知默认亮度值为102

 

2.     Lights框架层(java框架层和antive框架层)

接着1.2节,设备背光亮度的power.setBacklightBrightness() 在文件

\frameworks\base\core\java\android\os\IPowerManager.aidl中定义,如下:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. interfaceIPowerManager  
  2. {  
  3.               ……  
  4.               // sets the brightness of thebacklights (screen, keyboard, button) 0-255  
  5.     void setBacklightBrightness(intbrightness);  
  6.     void setBacklightBrightnessOff(booleanenable);  
  7.     void setMaxBrightness(int brightness);  
  8.               ……….  
  9. }  

IPowerManager.aidl,android系统提供了一种描述语言来定义具有跨进程访问能力的服务接口,这种描述语言称为Android接口描述语言(Android Interface Definition Language, AIDL)。以AIDL定义的服务接口文件以aidl为后缀名,在编译是,编译系统会将它们转换成java文件,这是需要在\frameworks\base\Android.mk

文件中添加对应的aidl文件,才会转换为java文件的,如:

[plain]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. LOCAL_SRC_FILES +=\  
  2. ……………  
  3. core/java/android/os/IPermissionController.aidl\  
  4.               core/java/android/os/IPowerManager.aidl\  
  5.               core/java/android/os/IRemoteCallback.aidl\  
  6. …………….  

然后再对它们进行编译。通常用于访问硬件的服务接口定义在\frameworks\base\core\java\android\os下。

 

IPowerManager只是提供服务的接口,具体的实在

frameworks\base\core\java\android\os\PowerManager.java中,如下:

  

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.    * sets the brightness of the backlights(screen, keyboard, button). 
  3.    * 
  4.    * @param brightness value from 0 to 255 
  5.    * 
  6.    * {@hide} 
  7.    */  
  8.   public void setBacklightBrightness(intbrightness)  
  9.   {  
  10.       try {  
  11.           mService.setBacklightBrightness(brightness);  
  12.       } catch (RemoteException e) {  
  13.       }  

这里调用PowerManagerService的接口,

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. frameworks\base\services\java\com\android\server\PowerManagerService.java,如下:  
  2.     public void setBacklightBrightness(intbrightness) {  
  3.        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,null);  
  4.         // Don't let applications turn thescreen all the way off  
  5.         synchronized (mLocks) {  
  6.             brightness = Math.max(brightness,mScreenBrightnessDim);  
  7.             if (mMaxBrightness > 0) {  
  8.                 if (brightness >mMaxBrightness) {  
  9.                     brightness =mMaxBrightness;  
  10.                 }  
  11.             }  
  12.             mLcdLight.setBrightness(brightness);  
  13.             //We won't adjust Button/KeyboardBKL here for the time being, see CR[ALPS00132847]  
  14.             //mKeyboardLight.setBrightness(mKeyboardVisible? brightness : 0);  
  15.            //mButtonLight.setBrightness(brightness);  
  16.             long identity =Binder.clearCallingIdentity();  
  17.             try {  
  18.                mBatteryStats.noteScreenBrightness(brightness);  
  19.             } catch (RemoteException e) {  
  20.                 Slog.w(TAG,"RemoteException calling noteScreenBrightness onBatteryStatsService", e);  
  21.             } finally {  
  22.                Binder.restoreCallingIdentity(identity);  
  23.             }  
  24.    
  25.             // update our animation state  
  26.             synchronized (mLocks) {  
  27.                 mScreenBrightness.targetValue =brightness;  
  28.                mScreenBrightness.jumpToTargetLocked();  
  29.             }  
  30.         }  
  31.     }  

(1)  mLcdLight赋值

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. …………..  
  2. static final int LIGHT_ID_BACKLIGHT = 0;  
  3. static final intLIGHT_ID_KEYBOARD = 1;  
  4. static final intLIGHT_ID_BUTTONS = 2;  
  5. static final intLIGHT_ID_BATTERY = 3;  
  6.   
  7. mLcdLight = lights.getLight(LightsService.LIGHT_ID_BACKLIGHT);  

(2)  setBrightness()

此函数位于frameworks\base\services\java\com\android\server\LightsService.java下,调用setBrightness()--->setLightLocked()--->setLight_native()。

 

LightsService.java声明的本地方法,也就是JNI接口函数有:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private staticnative int init_native();  
  2.     private static native voidfinalize_native(int ptr);  
  3.    
  4.     private static native void setLight_native(intptr, int light, int color, int mode,  
  5.             int onMS, int offMS, intbrightnessMode);  

这些本地方法在

frameworks\base\services\jni\com_android_server_LightsService.cpp下实现,先来看Andorid Java 和 C 函数的映射表数组:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. staticJNINativeMethod method_table[] = {  
  2.     { "init_native""()I",(void*)init_native },  
  3.     { "finalize_native","(I)V", (void*)finalize_native },  
  4.     { "setLight_native","(IIIIIII)V", (void*)setLight_native },  
  5. };  

JNINativeMethod结构体在dalvik\libnativehelper\include\nativehelper\jni.h

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. typedef struct {  
  2. const char* name;  
  3. const char*signature;  
  4. void* fnPtr;  
  5. } JNINativeMethod;  

第一个变量name是Java中函数的名字。

第二个变量signature,用字符串是描述了函数的参数和返回值

第三个变量fnPtr是函数指针,指向C/C++函数。

其中比较难以理解的是第二个参数,例如

"()V"

"(II)V"

"(Ljava/lang/String;Ljava/lang/String;)V"

实际上这些字符是与函数的参数类型一一对应的。

"()" 中的字符表示参数,后面的则代表返回值。例如"()V" 就表示void Func();

"(II)V" 表示 void Func(int, int);

详细可参考:http://blog.csdn.net/loongembedded/article/details/41355353

 

由此可见Java函数对应的CPP函数名字是一样的,在

frameworks\base\services\jni\com_android_server_LightsService.cpp中定义:

(1)  init_native()

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. static jintinit_native(JNIEnv *env, jobject clazz)  
  2. {  
  3.     int err;  
  4.     hw_module_t* module;  
  5.     Devices* devices;  
  6.      
  7.     devices =(Devices*)malloc(sizeof(Devices));  
  8.    
  9.     err =hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);  
  10.     if (err == 0) {  
  11.        devices->lights[LIGHT_INDEX_BACKLIGHT]  
  12.                 = get_device(module,LIGHT_ID_BACKLIGHT);  
  13.        devices->lights[LIGHT_INDEX_KEYBOARD]  
  14.                 = get_device(module,LIGHT_ID_KEYBOARD);  
  15.         devices->lights[LIGHT_INDEX_BUTTONS]  
  16.                 = get_device(module,LIGHT_ID_BUTTONS);  
  17.         devices->lights[LIGHT_INDEX_BATTERY]  
  18.                 = get_device(module,LIGHT_ID_BATTERY);  
  19.         devices->lights[LIGHT_INDEX_NOTIFICATIONS]  
  20.                 = get_device(module,LIGHT_ID_NOTIFICATIONS);  
  21.        devices->lights[LIGHT_INDEX_ATTENTION]  
  22.                 = get_device(module,LIGHT_ID_ATTENTION);  
  23.         devices->lights[LIGHT_INDEX_BLUETOOTH]  
  24.                 = get_device(module,LIGHT_ID_BLUETOOTH);  
  25.         devices->lights[LIGHT_INDEX_WIFI]  
  26.                 = get_device(module,LIGHT_ID_WIFI);  
  27.     } else {  
  28.         memset(devices, 0, sizeof(Devices));  
  29.     }  
  30.    
  31.     return (jint)devices;  
  32. }  


这里重点介绍hw_get_module()函数,声明如下:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. int hw_get_module(const char *id, const struct hw_module_t **module);  

id是输入参数,表示要加载的硬件抽象层模块ID;module是输出参数,如加载成功,它指向一个自定义的硬件抽象层模块结构体。函数返回值为0表示加载成功。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #defineHAL_LIBRARY_PATH1 "/system/lib/hw"  
  2. #defineHAL_LIBRARY_PATH2 "/vendor/lib/hw"  
  3. #defineHAL_LIBRARY_PATH3 "/system/lib"  

此函数回到这些路径下查找lights硬件抽象层模块lights.default.so并加载。

 

(2)  finalize_native()

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. static voidfinalize_native(JNIEnv *env, jobject clazz, int ptr)  
  2. {  
  3.     Devices* devices = (Devices*)ptr;  
  4.     if (devices == NULL) {  
  5.         return;  
  6.     }  
  7.    
  8.     free(devices);  
  9. }  

(3)  setLight_native()

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. static voidsetLight_native(JNIEnv *env, jobject clazz, int ptr,  
  2.         int light, int colorARGB, intflashMode, int onMS, int offMS, int brightnessMode)  
  3. {  
  4.     Devices* devices = (Devices*)ptr;  
  5.     light_state_t state;  
  6.    
  7.     if (light < 0 || light >= LIGHT_COUNT|| devices->lights[light] == NULL) {  
  8.         return ;  
  9.     }  
  10.    
  11.     memset(&state, 0,sizeof(light_state_t));  
  12.     state.color = colorARGB;  
  13.     state.flashMode = flashMode;  
  14.     state.flashOnMS = onMS;  
  15.     state.flashOffMS = offMS;  
  16.     state.brightnessMode = brightnessMode;  
  17.    
  18.     devices->lights[light]->set_light(devices->lights[light],&state);  
  19. }  

devices->lights[light]->set_light(devices->lights[light],&state);这里就是调用HAL层的函数。


3.     Lights硬件抽象层(HAL)

先来介绍这部分比较重要的结构体

3.1   light_state_t结构体

在hardware\libhardware\include\hardware\lights.h下定义:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * The parameters that can be set for a givenlight. 
  3.  * 
  4.  * Not all lights must support allparameters.  If you 
  5.  * can do something backward-compatible, youshould. 
  6.  */  
  7. structlight_state_t {  
  8.     /** 
  9.      * The color of the LED in ARGB. 
  10.      * 
  11.      * Do your best here. 
  12.      *  - If your light can only do red or green, if they ask for blue, 
  13.      *    you should do green. 
  14.      *  - If you can only do a brightness ramp, then use this formula: 
  15.      *     unsigned char brightness = ((77*((color>>16)&0x00ff)) 
  16.      *              +(150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8; 
  17.      *  - If you can only do on or off, 0 is off, anything else is on. 
  18.      * 
  19.      * The high byte should be ignored.  Callers will set it to 0xff (which 
  20.      * would correspond to 255 alpha). 
  21.      */  
  22.     unsigned int color;  
  23.    
  24.     /** 
  25.      * See the LIGHT_FLASH_* constants 
  26.      */  
  27.     int flashMode;  
  28.     int flashOnMS;  
  29.     int flashOffMS;  
  30.    
  31.     /** 
  32.      * Policy used by the framework to managethe light's brightness. 
  33.      * Currently the values areBRIGHTNESS_MODE_USER and BRIGHTNESS_MODE_SENSOR. 
  34.      */  
  35.     int brightnessMode;  
  36. };  

这里每个成员都有详细的解释,这里指强调几点:

(1)  flashMode成员

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /************************************************************************* 
  2.  * Flash modes for the flashMode field oflight_state_t. 
  3.  */  
  4.    
  5. #defineLIGHT_FLASH_NONE            0  
  6.    
  7. /** 
  8.  * To flash the light at a given rate, setflashMode to LIGHT_FLASH_TIMED, 
  9.  * and then flashOnMS should be set to thenumber of milliseconds to turn 
  10.  * the light on, followed by the number ofmilliseconds to turn the light 
  11.  * off. 
  12.  */  
  13. #defineLIGHT_FLASH_TIMED           1  
  14.    
  15. /** 
  16.  * To flash the light using hardware assist,set flashMode to 
  17.  * the hardware mode. 
  18.  */  
  19. #defineLIGHT_FLASH_HARDWARE        2  

表示LED等闪的模式,如果不需要闪烁为LIGHT_FLASH_NONE;如果需要软件来控制闪烁为LIGHT_FLASH_TIMED,这时也需要适当flashOnMS和flashOffMS的值;如果由硬件来控制闪烁的效果则为LIGHT_FLASH_HARDWARE。

 

(2)  brightnessMode成员

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * Light brightness is managed by a usersetting. 
  3.  */  
  4. #defineBRIGHTNESS_MODE_USER        0  
  5.    
  6. /** 
  7.  * Light brightness is managed by a lightsensor. 
  8.  */  
  9. #defineBRIGHTNESS_MODE_SENSOR      1  

BRIGHTNESS_MODE_USER表示由用户来设置背光,BRIGHTNESS_MODE_SENSOR表示有光传感器来自动调节背光,对应图4的Automatic brightness。

 

3.2   hw_module_t

在hardware\libhardware\include\hardware\hardware.h下定义:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /* 
  2.  * Value for the hw_module_t.tag field 
  3.  */  
  4.    
  5. #defineMAKE_TAG_CONSTANT(A,B,C,D) (((A) << 24) | ((B) << 16) | ((C)<< 8) | (D))  
  6.    
  7. #defineHARDWARE_MODULE_TAG MAKE_TAG_CONSTANT('H', 'W', 'M', 'T')  
  8. #defineHARDWARE_DEVICE_TAG MAKE_TAG_CONSTANT('H', 'W', 'D', 'T')  
  9. /** 
  10.  * Every hardware module must have a datastructure named HAL_MODULE_INFO_SYM 
  11.  * and the fields of this data structure mustbegin with hw_module_t 
  12.  * followed by module specific information. 
  13.  */  
  14. typedef structhw_module_t {  
  15.     /** tag must be initialized toHARDWARE_MODULE_TAG */  
  16.     uint32_t tag;  
  17.    
  18.     /** major version number for the module */  
  19.     uint16_t version_major;  
  20.    
  21.     /** minor version number of the module */  
  22.     uint16_t version_minor;  
  23.    
  24.     /** Identifier of module */  
  25.     const char *id;  
  26.    
  27.     /**Name of this module */  
  28.     const char *name;  
  29.    
  30.     /** Author/owner/implementor of the module*/  
  31.     const char *author;  
  32.    
  33.     /** Modules methods */  
  34.     struct hw_module_methods_t* methods;  
  35.    
  36.     /** module's dso */  
  37.     void* dso;  
  38.    
  39.     /** padding to 128 bytes, reserved forfuture use */  
  40.     uint32_t reserved[32-7];  
  41.    
  42. } hw_module_t;  

需要重点注意几点:

(1)  每个硬件抽象层都必须有个名为HAL_MODULE_INFO_SYM的结构体,而且它的第1个成员变量类型必须是hw_module_t。

(2)  结构体hw_module_t的成员变量dso用来保存加载硬件抽象层模块后得到的句柄值。前面提到,每一个硬件抽象层模块都对应有一个动态链接库文件。加载硬件抽象层模块的过程实际上就是调用dlopen函数来加载与其对应的动态链接库文件的过程。在调用dlclose函数来卸载这个硬件抽象层模块时,要用到这个句柄值,因此,我们在加载时需要将它保存起来。


(3)  methods

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. typedef structhw_module_methods_t {  
  2.     /** Open a specific device */  
  3.     int (*open)(const struct hw_module_t*module, const char* id,  
  4.             struct hw_device_t** device);  
  5.    
  6. }hw_module_methods_t;  

Open函数指针用来打开硬件抽象层模块的设备,参数module表示要打开的设备所在的模块;参数id表示要打开的设备的ID;参数device是一个输出参数,用来描述已经打开的设备。因为一个硬件抽象层模块可能包含多个设备,因为此在调用open的时候需要执行它的ID。

 

hw_device_t结构体的定义如下:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * Every device data structure must begin withhw_device_t 
  3.  * followed by module specific public methodsand attributes. 
  4.  */  
  5. typedef structhw_device_t {  
  6.     /** tag must be initialized toHARDWARE_DEVICE_TAG */  
  7.     uint32_t tag;  
  8.    
  9.     /** version number for hw_device_t */  
  10.     uint32_t version;  
  11.    
  12.     /** reference to the module this devicebelongs to */  
  13.     struct hw_module_t* module;  
  14.    
  15.     /** padding reserved for future use */  
  16.     uint32_t reserved[12];  
  17.    
  18.     /** Close this device */  
  19.     int (*close)(struct hw_device_t* device);  
  20.    
  21. } hw_device_t;  

需要注意几点:

1)     硬件抽象层模块中的每个设备都必须自定义一个设备结构体,而人气它的第1个成员变量类型必须是hw_device_t。

2)     close用来关闭一个设备。

 

根据上面结构体的定义可知,硬件抽象层中的设备是由其所在的模块提供的接口open来打开的,而关闭是由设备本身结构体提供的close接口来完成的。

 

3.3   light_device_t

在hardware\libhardware\include\hardware\lights.h下定义:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. structlight_device_t {  
  2.     struct hw_device_t common;  
  3.    
  4.     /** 
  5.      * Set the provided lights to the providedvalues. 
  6.      * 
  7.      * Returns: 0 on succes, error code onfailure. 
  8.      */  
  9.     int (*set_light)(struct light_device_t*dev,  
  10.             struct light_state_t const* state);  
  11. };  

下面给出mediatek\source\hardware\liblights\lights.c中相关的部分:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * module methods 
  3.  */  
  4.    
  5. /** Open a newinstance of a lights device using name */  
  6. static intopen_lights(const struct hw_module_t* module, char const* name,  
  7.         struct hw_device_t** device)  
  8. {  
  9.     int (*set_light)(struct light_device_t*dev,  
  10.             struct light_state_t const* state);  
  11.    
  12.     if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)){  
  13.         set_light =set_light_backlight;  
  14.     }  
  15.     elseif (0 == strcmp(LIGHT_ID_KEYBOARD, name)) {  
  16.         set_light = set_light_keyboard;  
  17.     }  
  18.     else if (0 == strcmp(LIGHT_ID_BUTTONS,name)) {  
  19.         set_light = set_light_buttons;  
  20.     }  
  21.     else if (0 == strcmp(LIGHT_ID_BATTERY,name)) {  
  22.         set_light = set_light_battery;  
  23.     }  
  24.     else if (0 ==strcmp(LIGHT_ID_NOTIFICATIONS, name)) {  
  25.         set_light = set_light_notifications;  
  26.     }  
  27.     else if (0 == strcmp(LIGHT_ID_ATTENTION,name)) {  
  28.         set_light = set_light_attention;  
  29.     }  
  30.     else {  
  31.        return -EINVAL;  
  32.     }  
  33.    
  34.     pthread_once(&g_init, init_globals);  
  35.    
  36.     struct light_device_t *dev =malloc(sizeof(struct light_device_t));  
  37.     memset(dev, 0, sizeof(*dev));  
  38.    
  39.     dev->common.tag = HARDWARE_DEVICE_TAG;  
  40.     dev->common.version = 0;  
  41.     dev->common.module = (structhw_module_t*)module;  
  42.     dev->common.close = (int (*)(structhw_device_t*))close_lights;  
  43.     dev->set_light = set_light;  
  44.    
  45.     *device = (struct hw_device_t*)dev;  
  46.     return 0;  
  47. }  
  48.    
  49.    
  50. static structhw_module_methods_t lights_module_methods = {  
  51.     .open = open_lights,  
  52. };  
  53.    
  54. /* 
  55.  * The lights Module 
  56.  */  
  57. const structhw_module_t HAL_MODULE_INFO_SYM = {  
  58.     .tag = HARDWARE_MODULE_TAG,  
  59.     .version_major = 1,  
  60.     .version_minor = 0,  
  61.     .id = LIGHTS_HARDWARE_MODULE_ID,  
  62.     .name = "MTK lights Module",  
  63.     .author = "MediaTek",  
  64.     .methods = &lights_module_methods,  
  65. };  

结合第2节的setLight_native()--->set_light (),对应调用的是set_light_backlight来设置背光。

 

3.4   set_light_backlight()

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /* LCD BACKLIGHT*/  
  2. char const*constLCD_FILE  
  3.         = "/sys/class/leds/lcd-backlight/brightness";  
  4.    
  5. static int  
  6. set_light_backlight(structlight_device_t* dev,  
  7.         struct light_state_t const* state)  
  8. {  
  9.     int err = 0;  
  10.     int brightness = rgb_to_brightness(state);// 将rgb亮度转化为亮度  
  11.     pthread_mutex_lock(&g_lock);  
  12. g_backlight = brightness;  
  13. //将数值写入sys文件系统的brightness文件  
  14.     err = write_int(LCD_FILE, brightness);  
  15.     if (g_haveTrackballLight) {  
  16.         handle_trackball_light_locked(dev);  
  17.     }  
  18.     pthread_mutex_unlock(&g_lock);  
  19.     return err;  
  20. }  

此函数主要是把新的背光亮度值brightness写入到/sys/class/leds/lcd-backlight/brightness文件中,比如103,然后LED驱动再读取此值,然后调节背光。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. static int  
  2. write_int(charconst* path, int value)  
  3. {  
  4.     int fd;  
  5.    
  6. #ifdefLIGHTS_INFO_ON  
  7.               LOGD("write %d to %s",value, path);  
  8. #endif  
  9.    
  10.     fd = open(path, O_RDWR);  
  11.     if (fd >= 0) {  
  12.         char buffer[20];  
  13.         int bytes = sprintf(buffer,"%d\n", value);  
  14.         int amt = write(fd, buffer, bytes);  
  15.         close(fd);  
  16.         return amt == -1 ? -errno : 0;  
  17.     } else {  
  18.         return -errno;  
  19.     }  
  20. }  

我们也可以通过echo(写)和cat(读)来设置背光亮度,如下图:


图5


4.     Lights驱动层

mediatek\config\hsimobile77_ics2\ProjectConfig.mkCUSTOM_KERNEL_LEDS=mt65xx

对于MTK平台,

根据上面的介绍,背光驱动提供的用于调节亮度接口是:/sys/class/leds/lcd-backlight/brightness。这个接口有LED驱动注册得来的的,源码位于Kernel/driver/leds/led-class.c中,下面给出其中一部分:

 

表示leds class的属性文件、权限和支持的操作

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. static struct device_attributeled_class_attrs[] = {  
  2.               __ATTR(brightness,0644, led_brightness_show, led_brightness_store),  
  3.               __ATTR(max_brightness, 0444,led_max_brightness_show, NULL),  
  4. #ifdefCONFIG_LEDS_TRIGGERS  
  5.               __ATTR(trigger, 0644,led_trigger_show, led_trigger_store),  
  6. #endif  
  7.               __ATTR_NULL,  
  8. };  
  9.    
  10. static int __initleds_init(void)  
  11. {  
  12.               leds_class =class_create(THIS_MODULE, "leds");  
  13.               if (IS_ERR(leds_class))  
  14.                              returnPTR_ERR(leds_class);  
  15.               leds_class->suspend =led_suspend;  
  16.               leds_class->resume =led_resume;  
  17.               leds_class->dev_attrs =led_class_attrs;  
  18.               return 0;  
  19. }  
  20. static void __exitleds_exit(void)  
  21. {  
  22.               class_destroy(leds_class);  
  23. }  
  24.    
  25. subsys_initcall(leds_init);  
  26. module_exit(leds_exit);  

这里主要是通过subsys_initcall来进行各种子系统的初始化。

 

Led-class.c文件只是实现了提供上层的接口,至于真正操作硬件的驱动程序,可以给出其源码路径为:(硬件操作其实就是脉宽调制(PWM)),mediatek\source\kernel\drivers\leds\leds.c

 

3.4节的set_light_backlight()通过write()把背光值写入到/sys/class/leds/lcd-backlight/brightness文件后,会触发调用led_brightness_store函数,经过led_brightness_store()--->led_set_brightness()--->led_cdev->brightness_set(led_cdev,value)的调用流程,最后调用到mt65xx_led_set(),这是通过mt65xx_leds_probe()的赋值语句知道的:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. g_leds_data[i]->cdev.brightness_set= mt65xx_led_set;  

这样我们就来看mt65xx_led_set()函数

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. static voidmt65xx_led_set(struct led_classdev *led_cdev, enum led_brightness level)  
  2. {  
  3.               struct mt65xx_led_data *led_data =  
  4.                              container_of(led_cdev,struct mt65xx_led_data, cdev);  
  5.    
  6.               // do something only when level ischanged  
  7.               if (led_data->level != level) {  
  8.                              led_data->level= level;  
  9.                              if(strcmp(led_data->cust.name,"lcd-backlight"))  
  10.                              {  
  11.                                                          schedule_work(&led_data->work);  
  12.                              }else  
  13.                              {  
  14.                                                          LEDS_DEBUG("[LED]SetBacklight directly %d at time %lu\n",led_data->level,jiffies);  
  15.                                                          mt65xx_led_set_cust(&led_data->cust,led_data->level);         
  16.                              }  
  17.               }  
  18. }  


调用mt65xx_led_set_cust()来实现,此函数的参数led_data->cust


[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. struct PWM_config  
  2. {  
  3.               int clock_source;  
  4.               int div;  
  5.               int low_duration;  
  6.               int High_duration;  
  7. };  
  8.    
  9. structcust_mt65xx_led {  
  10.               char                 *name;  
  11.               enum mt65xx_led_mode  mode;  
  12.               int                   data;  
  13.  struct PWM_config config_data;  
  14. };  
  15.    
  16. static structcust_mt65xx_led cust_led_list[MT65XX_LED_TYPE_TOTAL] = {  
  17.               {"red",               MT65XX_LED_MODE_NONE, -1,{0}},  
  18.               {"green",             MT65XX_LED_MODE_NONE, -1,{0}},  
  19.               {"blue",              MT65XX_LED_MODE_NONE, -1,{0}},  
  20.               {"jogball-backlight", MT65XX_LED_MODE_NONE,-1,{0}},  
  21.               {"keyboard-backlight",MT65XX_LED_MODE_NONE,-1,{0}},  
  22.               {"button-backlight",  MT65XX_LED_MODE_PMIC,MT65XX_LED_PMIC_BUTTON,{0}},  
  23. //           {"lcd-backlight",     MT65XX_LED_MODE_CUST,(int)Cust_SetBacklight,{0}},  
  24.               {"lcd-backlight",     MT65XX_LED_MODE_PWM,PWM1,{0}},           
  25. };  
  26.    
  27. structcust_mt65xx_led *get_cust_led_list(void)  
  28. {  
  29.               return cust_led_list;  
  30. }  


参数led_data->level就是当前要设置的背光值。

 

mt65xx_led_set_cust()--->backlight_set_pwm()--->pwm_set_spec_config()

 

在调试过程遇到的问题:

(1)  cust_mt65xx_ledcust_led_list全局结构体数组的修改

修改之前:{"lcd-backlight",     MT65XX_LED_MODE_GPIO,GPIO84,{0}},

因为我们是采用CPU的PWM1来控制背光的的,所以修改为:

{"lcd-backlight",     MT65XX_LED_MODE_PWM,PWM1,{0}},

可是进入系统后直接就是黑屏,为什么呢?根据调试信息知道/sys/class/leds/lcd-backlight/brightness文件的值为255,255是最大值,应该是最亮才对啊,但为什么是255就会黑屏呢?

看backlight_set_pwm()函数体下面的部分:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. if(level>0&& level <= 32)  
  2.               {  
  3.                              pwm_setting.PWM_MODE_FIFO_REGS.SEND_DATA0=  (1 << level) - 1 ;  
  4.                              pwm_setting.PWM_MODE_FIFO_REGS.SEND_DATA1= 0 ;  
  5.                              pwm_set_spec_config(&pwm_setting);  
  6.               }else if(level>32 &&level <=64)  
  7.               {  
  8.                              level -= 32;  
  9.                              pwm_setting.PWM_MODE_FIFO_REGS.SEND_DATA0=  0xFFFFFFFF ;  
  10.                              pwm_setting.PWM_MODE_FIFO_REGS.SEND_DATA1= (1 << level) - 1;  
  11.                              pwm_set_spec_config(&pwm_setting);  
  12.               }else  
  13.               {  
  14.                              LEDS_DEBUG("[LED]Errorlevel in backlight\n");  
  15.                              mt_set_pwm_disable(pwm_setting.pwm_no);  
  16.                              mt_power_off(pwm_setting.pwm_no);  
  17.               }  

因为level=255,所以就直接执行了关屏的动作,如果要搞清楚为什么level>64就要关屏,就要详细看MT6577的PWM部分了。

 

(2)  修改brightness_mapping()

上面出现在leve=255关屏的情况,为解决此问题就需要修改brightness_mapping()函数,看了为了确保上层设置0~255的情况下,是需要brightness_mapping函数的映射的,下面给出其实现部分:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. unsigned intbrightness_mapping(unsigned int level)  
  2. {  
  3.     unsigned int mapped_level;  
  4.     mapped_level = level;  
  5.      return mapped_level;  
  6. }  

很简单吧,为了解决此问题,我们改为:

mapped_level =level/4;

 

5.     Lights硬件层

参考我之前介绍的部分:

http://blog.csdn.net/loongembedded/article/details/38540297

 

6.     编译

./mk n ub、 ./mk n k和./mk bootimage,然后更新uboot_hsimobile77_ics2.bin和boot.img即可

 

参考:

mtk led

http://blog.csdn.net/mcgrady_tracy/article/details/41285213

 

android系统开发(七)-背光模块

http://blog.csdn.net/jiajie961/article/details/6030405

 

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

http://blog.sina.com.cn/s/blog_40d475e901014wkt.html

 

Android中背光系统架构

http://blog.csdn.net/yinwei520/article/details/6817528

 

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

http://blog.csdn.net/wealoong/article/details/7759178

 

lights从上到下的流程

http://blog.csdn.net/zhangchiytu/article/details/7958513

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/1618722.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu16.04设置背光灯发亮快捷键

Ubuntu16.04设置背光灯发亮快捷键 分三步&#xff1a; 1.新建根目录 mkdir ~/bin2编辑背光灯控制开关的脚本文件 vim ~bin/ledctrl将以下内容复制 #!/bin/bash - # # # FILE: ledctrl # # USAGE: ./ledctrl # # DESCRIPTION: # # OPTIONS: …

Linux c++开发-02-g++命令行编译

有如下的文件目录结构 格式一 swap.h swap.cpp main.cpp 编译方法和结果如下&#xff1a; 格式二 swap.cpp main.cpp 使用命令&#xff1a;g main.cpp src/swap.cpp -o main.exe 解决方法使用参数 -I 格式三-将swap.cpp生成一个静态库然后链接到main.cpp中 生成…

C语言文件操作收尾【随机读写 + 结束判定 + 文件缓冲区】

全文目录 前言fseek 重定位位置指示器函数ftell 获取当前文件指示器的位置rewind 重置位置指示器文本文件和二进制文件文件读取结束的判定feof 和 ferror 文件缓冲区总结 前言 有了文件的顺序读写基础&#xff0c;那么肯定会好奇文件的随机读写&#xff0c;毕竟顺序读写对于有…

python抢票开发——设备预约助手实现

女朋友是药学院的&#xff0c;做实验时需要在特定的网站上进行设备预约&#xff0c;由于预约人数过多&#xff0c;从而导致从浏览器登录不进去或者登录进去预约失败等情况&#xff0c;所以我用python帮她写了一个抢位助手&#xff0c;让程序自动去进行位置预定&#xff0c;实测…

春节Python抢票神器,支持候补抢票真的无敌了

想要回家的小伙伴们,大概经历了一波抢票大战。 一年一度春运着实让人难熬 这次顺便把一个Python抢票工具,送到了GitHub趋势榜第一。 项目名很干脆,就是12306,来自名叫文贤平的程序员。 这很可能是全GitHub最德高望重的购票小助手了,功能一直在更新,且现已支持Python …

Java IO流动(实战操作)

目录 1 IO流原理2 IO流的分类3 输入、输出流代码示例4 小结5 文件在前后台之间传递 在Java中&#xff0c;IO流是一种用于处理输入和输出操作的机制。它提供了一种统一的方式来读取和写入数据&#xff0c;平日开发中在文件读写&#xff0c;网络通信&#xff0c;特定场景的数据库…

老话题,火车票抢票助手,简化版 (漏洞已经失效^_^)

用了“二杠”兄弟的工具测试了抢票&#xff0c;先举个大拇指。牛&#xff01;可是我实在看不惯他画的界面&#xff0c;而且需要认证和访问他服务器上的wcf服务。看到许多园友都号称“破解”了。我也请出"Reflector"神器&#xff0c;尝试了下。发现把源exe文件作为app…

python模拟火车订票系统_如何用python编写火车抢票助手

前几天跟朋友说打算写一个抢票助手&#xff0c;最后由于某些原因念头打消了。 可就在昨天晚上&#xff0c;才隐约记起一年前的自己曾经说过&#xff1a;一年后我一定要写一个12306的抢票助手&#xff01;瞬间激情澎湃&#xff0c;甚至已经是快临近凌晨时便开始动工&#xff0c;…

无涯教程-Python机器学习 - Based on human supervision函数

Python机器学习 中的 Based on human s - 无涯教程网无涯教程网提供https://www.learnfk.com/python-machine-learning/machine-learning-with-python-based-on-human-supervision.html

Yolo系列-yolov3

YOLO-V3 这张图讲道理真的过分了&#xff01;&#xff01;&#xff01;我不是针对谁&#xff0c;在座的各位都是 终于到V3了&#xff0c;最大的改进就是网络结构&#xff0c;使其更适合小目标检测特征做的更细致&#xff0c;融入多持续特征图信息来预测不同规格物体 先验框更丰…

java 分布式游戏服务器框架,集群游戏服务器框架,游戏服务器网关框架 ioGame 网络游戏服务器框架

网络游戏框架简介 ioGame 是一个由 java 语言编写的网络游戏服务器框架。支持 websocket、tcp &#xff0c;适用于全球同服、回合制游戏、策略游戏、即时战斗等游戏服务器的开发。具有高性能、稳定、易用易扩展、超好编程体验等特点。可做为 H5、手游、端游的 java 游戏服务器…

游戏服务器架构通识

前言 这节讲座里&#xff0c;我们将从游戏服务器发展的简单历程出发&#xff0c;鸟瞰一下目前大多数的游戏服务器架构。 这里尽可能的避免陷入细节的技术问题&#xff0c;而是从技术进化的结果状态&#xff0c;反推原始问题是什么。希望能通过这个过程&#xff0c;解释清楚游戏…

游戏服务器架构设计整理

文章目录 前言一、单进程多线程的服务器设计模式&#xff0c;只有一个进程&#xff0c;但一个进程包好多个线程二、多进程单线程的服务器设计模式&#xff0c;多个进程&#xff0c;每个进程只有一个线程1.早期的MMORPG服务器结构2.中期-用户分离集群式3.中后期数据分离集群式4.…

游戏服务器被攻击了怎么办?

随着互联网的发展&#xff0c;网民数量激增&#xff0c;电子游戏的普及&#xff0c;庞大的玩家数量必然推动游戏市场发展。游戏受到攻击是游戏开发者的痛点&#xff0c;DDOS攻击是流量攻击的一个总称&#xff0c;还包括SYN Flood、ACK Flood、UDP Flood、TCP Flood、ICMP Flood…

经典游戏服务器端架构

文章目录 一、 讨论的背景二、 游戏服务器架构的要素三、核心的三个架构四、 游戏服务器模型的进化历程五、分服模型1.模型描述2.调度架构1.单进程游戏服务器2.多进程游戏服务器 3.内存架构1.动态内存2.预分配内存 4.进程间通讯手段1.Socket通讯2.消息队列3.远程调用 5.容灾和扩…

哪家的云游戏服务器好?如何选择云游戏服务器?

现如今&#xff0c;不少行业领域都对云服务器有不少的需求&#xff0c;尤其是游戏行业&#xff0c;需要专门的云游戏服务器。目前市场上的云游戏服务器有很多种类型&#xff0c;那么&#xff0c;哪家的云游戏服务器好呢&#xff1f;如何选择云游戏服务器&#xff1f;下面就跟着…

游戏开发商如何租用合适稳定的游戏服务器?

随着互联网的快速发展&#xff0c;网络游戏的发展令人目不暇接。有些游戏开发商在开发游戏时&#xff0c;对游戏服务器的要求非常高&#xff0c;毕竟一款游戏最重要的是流畅度。如果大量用户在玩游戏&#xff0c;而游戏直接因为服务器的宕机而崩溃&#xff0c;这种体验可能会直…

游戏服务器开发

1 2-课程概述 https://www.bilibili.com/video/BV1Ks41177oi?fromsearch&seid5543458349378694564nodejs lua STL IO 语言方面 精简 不像Python 无统一 游戏服务器 工作量 不是 网络连接 是 逻辑的 实现 定义 一个 struct 有两个成员 指针 和 值 …

从零开始搭建游戏服务器 第一节 创建一个简单的服务器架构

目录 引言技术选型正文创建基础架构IDEA创建项目添加Netty监听端口编写客户端进行测试 总结 引言 由于现在java web太卷了&#xff0c;所以各位同行可以考虑换一个赛道&#xff0c;做游戏还是很开心的。 本篇教程给新人用于学习游戏服务器的基本知识&#xff0c;给新人们一些…

鹅厂公开课:游戏服务器,了解一下?

讲师简介&#xff1a;张正&#xff0c;腾讯互娱北极光工作室群专家工程师&#xff0c;拥有12年游戏后台开发经验&#xff0c;主导和参与了《天涯明月刀》、《轩辕传奇》等自研大型MMORPG项目的后台开发&#xff0c;现担任《天涯明月刀》项目后台技术总监&#xff0c;北极光后台…