展訊7731C_M Android6.0 充電指示燈實現(一)------關機充電實現
阿新 • • 發佈:2019-02-19
轉載:https://blog.csdn.net/xiaopangzi313/article/details/52194513
前言:
在手機充電中常常使用充電指示燈來觀察手機充電狀態,比如說將手機插上USB線充電時指示燈會亮,如果拔出USB,指示燈會滅,在充電時候通常我們設定電池電量0~90%時,指示燈為紅色,電量為90%~100%時候,顯示為綠色。當然充電又分為開機充電和
關機充電,本文著重從關機充電模式講解guide-led的實現機制
一、關機充電下,指示燈實現整體流程框架
在關機下,插入USB充電,系統會上電啟動核心,並且載入相關的服務(Linux 使用者空間程序),其中就有關機充電服務/sytem/bin/charge,其中服務端的啟動定義在開機初始化話檔案init.rc中,如下:
- service charge /bin/charge
- user root
- oneshot
實現流程框架圖如下:
該圖可以分為兩個部分,Linux user和kernel 層兩個部分,charge 執行從建立charge執行緒開始到呼叫kernel set_brightness完成
對guide-led的控制。
二、關機充電下,指示燈實現具體流程
==========linux user process部分==========1. 電池充電主程式入口
- int
- main(int argc,
- .....
- 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
- }
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;
- }
將電池容量不斷的傳入update_progress_locked方法中
3.update_progress_locked方法的實現
- staticvoid 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
- staticvoid draw_progress_locked(int level)
- {
- .....
- if(level > 100)
- level = 100; //處理電池電量的上限
- elseif (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的實現
- 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);
- }elseif(color == 2){
- eng_led_red_test(max_red_led/2);
- eng_led_green_test(0);
- eng_led_blue_test(0);
- }elseif(color == 3){
- eng_led_blue_test(0);
- eng_led_red_test(max_green_led/2);
- eng_led_green_test(max_red_led/2);
- }else
- SPRD_DBG("%s: color is %d invalid\n",__func__,color);
- }
6. 亮綠燈函式eng_led_green_test的實現
- staticint 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;
- }
#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寫函式實現
- static ssize_t store_on_off(struct device *dev,
- struct device_attribute *attr, constchar *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: