展讯7731C_M Android6.0 充电指示灯实现(一)------关机充电实现
前言:
在手机充电中常常使用充电指示灯来观察手机充电状态,比如说将手机插上USB线充电时指示灯会亮,如果拔出USB,指示灯会灭,在充电时候通常我们设置电池电量0~90%时,指示灯为红色,电量为90%~100%时候,显示为绿色。当然充电又分为开机充电和
关机充电,本文着重从关机充电模式讲解guide-led的实现机制
一、关机充电下,指示灯实现整体流程框架
在关机下,插入USB充电,系统会上电启动内核,并且加载相关的服务(Linux 用户空间进程),其中就有关机充电服务/sytem/bin/charge,其中服务端的启动定义在开机初始化话文件init.rc中,如下:
service charge /bin/chargeuser rootoneshot
其中charge程序由 vendor/sprd/open-source/apps/charge/charge.c实现。
实现流程框架图如下:
该图可以分为两个部分,Linux user和kernel 层两个部分,charge 执行从创建charge线程开始到调用kernel set_brightness完成
对guide-led的控制。
二、关机充电下,指示灯实现具体流程
1. 电池充电主程序入口
文件:vendor/sprd/open-source/apps/charge/charge.c
int
main(int argc, char **argv) {.....ret = pthread_create(&t_1, NULL, charge_thread, NULL);if(ret){LOGE("thread:charge_thread creat failed\n");return -1;}LOGD("all thread start\n");pthread_join(t_1, NULL);.....LOGD("charge app exit\n");return EXIT_SUCCESS;
}
在主程序中,创建charge_thread用来检测电池状态,然后根据充电电量的变化来控制充电指示灯
2. 充电线程的定义
文件: vendor/sprd/open-source/apps/charge/ui.c
#define WakeFileName "/sys/power/wait_for_fb_wake"
void *charge_thread(void *cookie)
{.....for (;!is_exit;) {fd = open(WakeFileName, O_RDONLY, 0);if (fd < 0) {LOGD("Couldn't open file /sys/power/wait_for_fb_wake\n");return NULL;}do {err = read(fd, &buf, 1);LOGD("return from WakeFileName err: %d errno: %s\n", err, strerror(errno));} while (err < 0 && errno == EINTR);close(fd);bat_level = battery_capacity();update_progress_locked(bat_level);usleep(500000);}......usleep(200);return NULL;
}
改线程中有一个循环体,其中battery_capacity用来获取电池容量,
将电池容量不断的传入update_progress_locked方法中
3.update_progress_locked方法的实现
static void update_progress_locked(int level)
{......draw_progress_locked(level); // Draw only the progress bar}
在update_progress_locked中,又调用draw_progress_locked方法
4.draw_process_locked方法的实现
#define LED_GREEN 1
#define LED_RED 2
#define LED_BLUE 3
static void draw_progress_locked(int level)
{.....if(level > 100)level = 100; //处理电池电量的上限else if (level < 0)//处理电池电量的下限level = 0; if(level < 90){if(led_flag!= LED_RED){led_on(LED_RED);led_flag = LED_RED; //如果电池电量低于90亮绿灯}}else{if(led_flag!= LED_GREEN){ //如果电池电量90~100 亮红灯led_on(LED_GREEN); //调用亮灯函数led_flag = LED_GREEN;}}.....
}
5. 亮灯函数led_on的实现
文件:vendor/sprd/open-source/apps/charge/backlight.c
void led_on(int color)
{if(color == 1){eng_led_green_test(max_green_led/2);eng_led_red_test(0);eng_led_blue_test(0);}else if(color == 2){eng_led_red_test(max_red_led/2);eng_led_green_test(0);eng_led_blue_test(0);}else if(color == 3){eng_led_blue_test(0);eng_led_red_test(max_green_led/2);eng_led_green_test(max_red_led/2);}elseSPRD_DBG("%s: color is %d invalid\n",__func__,color);
}
在亮灯函数led_on 中, 通过传入的参数clor 来区分不能颜色灯,这里以绿灯为例
6. 亮绿灯函数eng_led_green_test的实现
static int eng_led_green_test(int brightness)
{int fd;int ret;char buffer[8];fd = open(LED_GREEN_DEV, O_RDWR); //打开绿灯设备节点if(fd < 0) {SPRD_DBG("%s: open %s fail",__func__, LED_GREEN_DEV);return -1;}memset(buffer, 0, sizeof(buffer));sprintf(buffer, "%d", brightness);ret = write(fd, buffer, strlen(buffer)); //向节点中写入数据brightness值close(fd);return 0;
}
亮绿灯函数eng_led_green_test的实现非常容易,就是向指定的节点中写入数据brightness值,而brightness值的范围为0~255 ,这个值直接决定了pwm输入的占空比,进而影响灯的亮度。查看设备节点定义如下:
#define LED_GREEN_DEV "/sys/class/leds/green/brightness"
#define LED_RED_DEV "/sys/class/leds/red/brightness"
#define LED_BLUE_DEV "/sys/class/leds/blue/brightness"
上面的节点分别对应为红,绿,蓝三色灯对应的控制节点
==========linux driver kernel 部分==========
也就是说当我们调用write接口后,应用层点灯过程就已经结束了,接下来write会通过Linux VFS调用底层的xxx_write函数,
由于这里定义为/sys 目录下的设备模型节点,所以对应写函数应该为 xxx_store_xxx才对。
7.驱动层的led_on写函数实现
文件:kernel/drivers/leds/leds-sprd-bltc-rgb.c
static ssize_t store_on_off(struct device *dev,struct device_attribute *attr, const char *buf, size_t size)
{struct led_classdev *led_cdev = dev_get_drvdata(dev);unsigned long state;ssize_t ret = -EINVAL;ret = kstrtoul(buf, 10, &state);PRINT_INFO("onoff_state_value:%1ld\n",state);onoff_value = state;led_cdev->flags = ONOFF;sprd_leds_bltc_rgb_set(led_cdev,state);return size;
}
在上述的写函数中又调用sprd_leds_bltc_rgb_set函数,并且将brightness值传入
8.sprd_leds_bltc_rgb_set的实现
static void sprd_leds_bltc_rgb_set(struct led_classdev *bltc_rgb_cdev,enum led_brightness value)
{struct sprd_leds_bltc_rgb *brgb;unsigned long flags;brgb = to_sprd_bltc_rgb(bltc_rgb_cdev);spin_lock_irqsave(&brgb->value_lock, flags);brgb->leds_flag = bltc_rgb_cdev->flags;brgb->value = value;spin_unlock_irqrestore(&brgb->value_lock, flags);if(1 == brgb->suspend) {PRINT_WARN("Do NOT change brightness in suspend mode\n");return;}if(strcmp(brgb->cdev.name,sprd_leds_rgb_name[SPRD_LED_TYPE_R]) == 0 || \strcmp(brgb->cdev.name,sprd_leds_rgb_name[SPRD_LED_TYPE_G]) == 0 || \strcmp(brgb->cdev.name,sprd_leds_rgb_name[SPRD_LED_TYPE_B]) == 0)sprd_leds_rgb_work(brgb);elsesprd_leds_bltc_work(brgb);
}
在上述的写函数中又调用sprd_leds_bltc_work函数
9.sprd_leds_bltc_work的实现
static void sprd_leds_rgb_work(struct sprd_leds_bltc_rgb *brgb)
{unsigned long flags;mutex_lock(&brgb->mutex);spin_lock_irqsave(&brgb->value_lock, flags);if (brgb->value == LED_OFF) {spin_unlock_irqrestore(&brgb->value_lock, flags);sprd_leds_bltc_rgb_set_brightness(brgb);goto out;}spin_unlock_irqrestore(&brgb->value_lock, flags);sprd_leds_bltc_rgb_enable(brgb);PRINT_INFO("sprd_leds_bltc_rgb_work_for rgb!\n");out:mutex_unlock(&brgb->mutex);
}
紧接着又调用sprd_leds_bltc_rgb_enable接口
10.sprd_leds_bltc_rgb_enable的实现
static void sprd_leds_bltc_rgb_enable(struct sprd_leds_bltc_rgb *brgb)
{sprd_bltc_rgb_init(brgb);if(strcmp(brgb->cdev.name,sprd_leds_rgb_name[SPRD_LED_TYPE_R]) == 0) {sci_adi_set(brgb->sprd_bltc_base_addr + BLTC_CTRL, (0x1<<0)|(0x1<<1));brgb->bltc_addr = brgb->sprd_bltc_base_addr + BLTC_R_PRESCL + BLTC_DUTY_OFFSET;sprd_leds_bltc_rgb_set_brightness(brgb);}if(strcmp(brgb->cdev.name,sprd_leds_rgb_name[SPRD_LED_TYPE_G]) == 0) {sci_adi_set(brgb->sprd_bltc_base_addr + BLTC_CTRL, (0x1<<4)|(0x1<<5));brgb->bltc_addr = brgb->sprd_bltc_base_addr + BLTC_G_PRESCL + BLTC_DUTY_OFFSET;sprd_leds_bltc_rgb_set_brightness(brgb);}if(strcmp(brgb->cdev.name,sprd_leds_rgb_name[SPRD_LED_TYPE_B]) == 0) {sci_adi_set(brgb->sprd_bltc_base_addr + BLTC_CTRL, (0x1<<8)|(0x1<<9));brgb->bltc_addr = brgb->sprd_bltc_base_addr + BLTC_B_PRESCL + BLTC_DUTY_OFFSET;sprd_leds_bltc_rgb_set_brightness(brgb);}.....PRINT_INFO("sprd_leds_bltc_rgb_enable\n");brgb->enable = 1;
}
紧接着又调用sprd_leds_bltc_rgb_set_brightness
11.sprd_leds_bltc_rgb_set_brightness的实现
static void sprd_leds_bltc_rgb_set_brightness(struct sprd_leds_bltc_rgb *brgb)
{unsigned long brightness = brgb->value;unsigned long pwm_duty;pwm_duty = brightness;if(pwm_duty > 255)pwm_duty = 255;sci_adi_write(brgb->bltc_addr, (pwm_duty<<8)|PWM_MOD_COUNTER,0xffff);PRINT_INFO("reg:0x%1LX set_val:0x%08X brightness:%ld brightness_level:%ld(0~15)\n", \brgb->bltc_addr, sprd_leds_bltc_rgb_read(brgb->bltc_addr),brightness, pwm_duty);
}
这里使用最关键的一步使用 sci_adi_write 将ISINK 寄存器赋值,直接调整亮度
三、总结
PS:本文侧重关机充电,当然也牵扯到部分Kernel 部分,至于kernel部分详细实现后面开机充电会详述说明。
展讯7731C_M Android6.0 充电指示灯实现(一)------关机充电实现相关推荐
- 展讯7731C_M Android6.0 充电指示灯实现
http://blog.csdn.net/xiaopangzi313/article/details/52199407 上一节已经了解了展讯7731C_M Android6.0 充电指示灯实的关机部分 ...
- 展讯7731C_M Android6.0 充电指示灯实现(一)------关机充电实现【转】
本文转载自:https://blog.csdn.net/m0_37870649/article/details/80566131 前言: 在手机充电中常常使用充电指示灯来观察手机充电状态,比如说将手机 ...
- android 10.0 展讯 MTK内置可卸载app
1.概述 在进行10.0的产品定制化开发中,展讯内置可卸载恢复的app 其实把apk编译到system/proloadapp 目录下即可 2.展讯 MTK内置可卸载app的实现步骤 实现方式: 1 预 ...
- 关于android各种双卡手机获取imei,imsi的处置(mtk,展讯,高通等)
2019独角兽企业重金招聘Python工程师标准>>> 关于android各种双卡手机获取imei,imsi的处理(mtk,展讯,高通等) 目前国内对于双卡智能手机的需求还是很大的, ...
- Android 系统(98)---Android app 在线更新那点事儿(适配Android6.0、7.0、8.0)
Android app 在线更新那点事儿(适配Android6.0.7.0.8.0) 一.前言 app在线更新是一个比较常见需求,新版本发布时,用户进入我们的app,就会弹出更新提示框,第一时间更新新 ...
- 展讯sprd_battery.c 充电驱动
sprd_battery.c 是充电驱动,这个是充电功能的核心内容,电量显示策略.温度检测策略.充电保护机制等功能在这里实现,功能实现与硬件细节剥离,调用通用接口实现逻辑控制: 1 sprdbat_p ...
- 7 展讯Sprd设置-电池-关联自启动-跟踪代码
1. UI-关联自启动 2. 源码走读-上层接口调用 2.1 字符串 strings_ex.xml <string name="app_as_lunch">关联启动&l ...
- 小米屏和展讯屏幕调试参考 写的较好(有发送速率)
MIPI LCD调试总结 http://blog.csdn.net/richu123/article/details/51394464 近来在用SSD2828驱动小米屏,没有代码,没有技术支持,自己写 ...
- 展讯走出困境开始爬坡
2009年8月19日展讯发布Q2财报,虽然依然亏随1310万美元,不过从近几个季度财报分析,展讯已经走出2008年以来的低谷,开始迅速爬坡,按照展讯公布的财报预计2009年Q3营收将超过3100万美元 ...
最新文章
- AI产业链全景图!【物联网智商精选】
- Layer 2 Tunneling Protocol
- EF框架对数据库的操作
- JS学习笔记:防止发生命名冲突
- 80211 发送速率选择算法分析
- 腾讯视频怎么禁止别人登录我的会员
- rowdata java_Java RowDataUtil.addRowData方法代碼示例
- 任正非:华为欲出售5G技术制造竞争对手
- 制图折断线_无锡春华教育AutoCAD家具制图/机械/工程制图
- PosgreSQL快速参数调优和sysbench压测
- 当前读和快照读是什么 区别
- 201111-W-网络技术-基础理论与应用说明
- WordPress漏洞扫描器wpscan
- (八)冰点还原安装及使用
- WEB学习第四天(网页模型
- android6.0相机假对焦,android相机对焦
- webscraper多页爬取_Web Scraper 高级用法——Web Scraper 抓取多条内容 | 简易数据分析 07...
- 安装html5 win7,win7官方正版64位系统安装教程
- HTML px em pt长度单位(像素 相对长度 点)
- pygame战棋游戏制作之战棋光标设置上(三)