Android 充电LED控制
发布日期:2021-06-30 18:55:01 浏览次数:2 分类:技术文章

本文共 6907 字,大约阅读时间需要 23 分钟。

1、前言

充电LED灯控制是Android设备的基本功能,主要用于提示设备的电池状态,充电状态,满电状态,低电状态,很多手机厂商还使用呼吸效果来显示,普通的低端设备会使用两个LED灯表示,红灯表示充电和低电,绿灯表示满电。

 

之前写的文章 《》

2、kernel 层控制充电LED

代码位置主要在kernel/driver/power/power_supply_leds.c

 

/* Battery specific LEDs triggers. */static void power_supply_update_bat_leds(struct power_supply *psy){    union power_supply_propval status;    unsigned long delay_on = 0;    unsigned long delay_off = 0;    if (power_supply_get_property(psy, POWER_SUPPLY_PROP_STATUS, &status))        return;    dev_dbg(&psy->dev, "%s %d\n", __func__, status.intval);    switch (status.intval) {    case POWER_SUPPLY_STATUS_FULL:        led_trigger_event(psy->charging_full_trig, LED_FULL);        led_trigger_event(psy->charging_trig, LED_OFF);        led_trigger_event(psy->full_trig, LED_FULL);        led_trigger_event(psy->charging_blink_full_solid_trig,            LED_FULL);        break;    case POWER_SUPPLY_STATUS_CHARGING:        led_trigger_event(psy->charging_full_trig, LED_FULL);        led_trigger_event(psy->charging_trig, LED_FULL);        led_trigger_event(psy->full_trig, LED_OFF);        led_trigger_blink(psy->charging_blink_full_solid_trig,            &delay_on, &delay_off);        break;    default:        led_trigger_event(psy->charging_full_trig, LED_OFF);        led_trigger_event(psy->charging_trig, LED_OFF);        led_trigger_event(psy->full_trig, LED_OFF);        led_trigger_event(psy->charging_blink_full_solid_trig,            LED_OFF);        break;    }}

 

如果想在kernel 层控制led灯,就需要在这里修改代码,会需要使用到trigger相关的东西,要理解什么是trigger,可以看下面的链接

 

trigger主要是做led灯的一些效果的东西,默认有default-on 对应打开led的trigger,还有none对应关闭LED的trigger。

 

被[ ]括起来的,就是当前trigger的值,然后回触发对应trigger的.activate函数。

Trigger的代码位置在 kernel/drivers/leds/trigger

3、framework控制led灯

为了统一控制led接口,Android有一个自己的框架控制led灯

Framework->Hal->kernel->hardware

设置对应的LED灯颜色主要在

Framework/base/core/res/res/values/config.xml

#ffffffff
500
2000
0xFFFF0000
0xFFFF0000
0xFF00FF00
125

 

充电状态灯指示状态函数调用

frameworks\base\services\core\java\com\android\server\BatteryService.java

/*** Synchronize on BatteryService.*/public void updateLightsLocked() {final int level = mBatteryProps.batteryLevel;final int status = mBatteryProps.batteryStatus;if (level < mLowBatteryWarningLevel) {    if (status == BatteryManager.BATTERY_STATUS_CHARGING) {        // Solid red when battery is charging        mBatteryLight.setColor(mBatteryLowARGB);    } else {        // Flash red when battery is low and not charging        mBatteryLight.setFlashing(mBatteryLowARGB, Light.LIGHT_FLASH_TIMED,        mBatteryLedOn, mBatteryLedOff);    }} else if (status == BatteryManager.BATTERY_STATUS_CHARGING|| status == BatteryManager.BATTERY_STATUS_FULL) {    if (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90) {    // Solid green when full or charging and nearly full        mBatteryLight.setColor(mBatteryFullARGB);    } else {        if (isHvdcpPresent()) {            // Blinking orange if HVDCP charger            mBatteryLight.setFlashing(mBatteryMediumARGB, Light.LIGHT_FLASH_TIMED,            mBatteryLedOn, mBatteryLedOn);        } else {            // Solid orange when charging and halfway full            mBatteryLight.setColor(mBatteryMediumARGB);        }    }} else {    // No lights if not charging and not low    mBatteryLight.turnOff();}}}

 

LightsService 管理LED

frameworks\base\services\core\java\com\android\server\lights\LightsService.java

private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode);{//调用JNI函数设置状态setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);}static void setLight_native(JNIEnv* /* env */, jobject /* clazz */, jlong ptr,jint light, jint colorARGB, jint flashMode, jint onMS, jint offMS, jint brightnessMode){//调用HAL层接口设置指示灯状态devices->lights[light]->set_light(devices->lights[light], &state);}

 

获取HAL层接口函数

static jlong init_native(JNIEnv* /* env */, jobject /* clazz */){int err;hw_module_t* module;Devices* devices;devices = (Devices*)malloc(sizeof(Devices));err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);if (err == 0) {    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);    devices->lights[LIGHT_INDEX_BLUETOOTH] = get_device(module, LIGHT_ID_BLUETOOTH);    devices->lights[LIGHT_INDEX_WIFI] = get_device(module, LIGHT_ID_WIFI);} else {    memset(devices, 0, sizeof(Devices));}return (jlong)devices;}

 

中间层的代码位置主要在

Hardware/rockchip/liblight/

一个字节对应一种颜色,一共有三个颜色,想最终控制颜色就需要修改上面说的xml文件,比如0x00ffffff,表示红蓝绿三个灯同时亮。具体代码如下

int set_battery_light(struct light_device_t* dev, struct light_state_t const* state){                                         int err = 0;                          char red,blue,green;                  unsigned int colorRGB = state->color & 0x00ffffff;    red = (colorRGB >> 16) & 0xFF;     green = (colorRGB >> 8) & 0xFF;                                                                                        blue = colorRGB & 0xFF;               pthread_mutex_lock(&g_lock);       LOGI(">>>weiqifa set_battery_light 0x%x",state->color);    err = write_int(RED_LED_PATH, red?1:0);    err = write_int(BLUE_LED_PATH, blue?1:0);    err = write_int(GREEN_LED_PATH, green?1:0);    pthread_mutex_unlock(&g_lock);     return 0;                         }

 

然后控制的主要是led的设备节点,led的设备节点主要是驱动层生成,代码的位置如下:kernel/driver/leds/

#define RED_LED_PATH "sys/class/leds/red/brightness"
#define GREEN_LED_PATH "sys/class/leds/green/brightness"
#define BLUE_LED_PATH "sys/class/leds/blue/brightness"

 

 

Led驱动对应的dts代码如下:

leds: gpio-leds {        compatible = "gpio-leds";        led-green {        ┊   label = "green";            gpios = <&gpio7 8 GPIO_ACTIVE_HIGH>;            inux,default-trigger = "timer";            default-state = "off";        };         led-blue {        ┊   label = "blue";            gpios = <&gpio7 14 GPIO_ACTIVE_HIGH>;            inux,default-trigger = "timer";            default-state = "off";        };         led-red {        ┊   label = "red";            gpios = <&gpio7 15 GPIO_ACTIVE_HIGH>;            inux,default-trigger = "timer";                                                                                        default-state = "off";        };    };

里面的linux,default-trigger 表示默认的trigger模式,如果设置为none就是表示关闭,现在我们的代码设置为timer表示用定时器的模式,实际上我们没有编译定时器模式,所以设置并没有生效。

 

欢迎关注微信公众号-嵌入式Linux

觉得不错,请帮忙转发,点赞,您的每一次支持,我都将铭记于心

转载地址:https://linus.blog.csdn.net/article/details/84999154 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:老王带你理解算法复杂度O(1),O(N),O(N^2)
下一篇:C语言测试n的阶乘和x的n次方

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2024年04月12日 09时16分07秒