操作qtopia2.2.0電池圖標顯示電池電量

操作qtopia2.2.0電池圖標顯示電池電量
  
    想讓qtopia2.2.0下的電池圖標顯示電池的實際狀態,一開始不知道怎麼操作,在網上也找不到相應的教程,也沒有qtopia2.2.0的api文檔。剛開始感覺沒有辦法解決,想了好多替代方法,感覺都不好,最後只好去qtopia2.2.0的源碼中去尋找,看看能不能找到點蛛絲馬跡(一開始不想去源碼裏找,感覺太麻煩,但事實證明看源碼是一個好方法)。

    在qtopia2.2.0下設置程序組下的Plugin Manager軟件裏可添加和刪除屏幕右下角的幾個小程序,比如背光調節、音量調節、電池電量等。
    在qtopia2.2.0的源碼中搜索"battery"(grep "battery*"  ./  -nr),出現次數比較多的源碼文件是

/root/work/mini6410/linux/arm-qtopia/qtopia-2.2.0-FriendlyARM/qtopia/src/plugins/applets/batteryapplet/battery.cpp

/root/work/mini6410/linux/arm-qtopia/qtopia-2.2.0-FriendlyARM/qtopia/src/plugins/applets/batteryapplet/batterystatus.cpp

/root/work/mini6410/linux/arm-qtopia/qtopia-2.2.0-FriendlyARM/qtopia/src/settings/light-and-power/light.cpp

打開battery.cpp和batterystatus.cpp可以看到qt對電池圖標的變化已經做了很好的支持。
在\arm-qtopia\qtopia-2.2.0-friendlyarm\qtopia\src\libraries\qtopia\Power.cpp中看到如下代碼:

  1 #include "power.h"
  2 
  3 #include "custom.h"
  4 
  5 #include <stdlib.h>
  6 #include <stdio.h>
  7 #include <fcntl.h>
  8 #if defined(Q_OS_LINUX) || defined(_OS_LINUX_)
  9 #include <sys/ioctl.h>
 10 #include <unistd.h>
 11 #endif
 12 
 13 #ifdef QT_QWS_IPAQ_NO_APM
 14 #include <linux/h3600_ts.h>
 15 #endif
 16 
 17 PowerStatusManager *PowerStatusManager::powerManager = 0;
 18 PowerStatus *PowerStatusManager::ps = 0;
 19 
 20 PowerStatusManager::PowerStatusManager()
 21 {
 22     powerManager = this;
 23     ps = new PowerStatus;
 24 }
 25 
 26 const PowerStatus &PowerStatusManager::readStatus()
 27 {
 28     if ( !powerManager ) {
 29     (void)new PowerStatusManager;
 30     }
 31 
 32     powerManager->getStatus();
 33 
 34     return *ps;
 35 }
 36 
 37 // Standard /proc/apm reader
 38 bool PowerStatusManager::getProcApmStatus( int &ac, int &bs, int &bf, int &pc, int &sec )
 39 {
 40     bool ok = false;
 41 
 42     ac = 0xff;
 43     bs = 0xff;
 44     bf = 0xff;
 45     pc = -1;
 46     sec = -1;
 47 
 48     FILE *f = fopen("/proc/apm", "r");
 49     if ( f ) {
 50     //I 1.13 1.2 0x02 0x00 0xff 0xff 49% 147 sec
 51     char u;
 52     fscanf(f, "%*[^ ] %*d.%*d 0x%*x 0x%x 0x%x 0x%x %d%% %i %c",
 53         &ac, &bs, &bf, &pc, &sec, &u);
 54     fclose(f);
 55     switch ( u ) {
 56         case 'm': sec *= 60;
 57         case 's': break; // ok
 58         default: sec = -1; // unknown
 59     }
 60 
 61     // extract data
 62     switch ( bs ) {
 63         case 0x00:
 64         ps->bs = PowerStatus::High;
 65         break;
 66         case 0x01:
 67         ps->bs = PowerStatus::Low;
 68         break;
 69         case 0x7f:
 70         ps->bs = PowerStatus::VeryLow;
 71         break;
 72         case 0x02:
 73         ps->bs = PowerStatus::Critical;
 74         break;
 75         case 0x03:
 76         ps->bs = PowerStatus::Charging;
 77         break;
 78         case 0x04:
 79         case 0xff: // 0xff is Unknown but we map to NotPresent
 80         default:
 81         ps->bs = PowerStatus::NotPresent;
 82         break;
 83     }
 84 
 85     switch ( ac ) {
 86         case 0x00:
 87         ps->ac = PowerStatus::Offline;
 88         break;
 89         case 0x01:
 90         ps->ac = PowerStatus::Online;
 91         break;
 92         case 0x02:
 93         ps->ac = PowerStatus::Backup;
 94         break;
 95     }
 96 
 97     if ( pc > 100 )
 98         pc = -1;
 99 
100     ps->percentRemain = pc;
101     ps->secsRemain = sec;
102 
103     ok = true;
104     } else {
105        ps->bs = PowerStatus::NotPresent;
106        pc = sec = -1;
107        ps->percentRemain = -1;
108        ps->secsRemain = -1;
109     }
110     
111 
112     return ok;
113 }
114 
115 const bool PowerStatusManager::APMEnabled() 
116 {
117     int apm_install_flags;
118     FILE *f = fopen("/proc/apm", "r");
119     if ( f ) {
120     //I 1.13 1.2 0x02 0x00 0xff 0xff 49% 147 sec
121     fscanf(f, "%*[^ ] %*d.%*d 0x%x 0x%*x 0x%*x 0x%*x %*d%% %*i %*c",
122         &apm_install_flags);
123     fclose(f);
124 
125         if (!(apm_install_flags & 0x08)) //!APM_BIOS_DISABLED
126         {
127             return TRUE;
128         }
129     }
130     return FALSE;
131 }
從以上代碼知道了,qt的電源狀態信息是從/proc/apm中得到的,那麼只要操作/proc/apm,電源圖標的狀態就會相應改變了。

回到驅動,/proc/apm的創建和操作是在drivers/char/apm-emulation.c中實現的,apm-emulation.c中不僅實現了電源狀態的操作還實現了系統的休眠和喚醒,爲了做一個測試,只把apm-emulation.c中關於操作/proc/apm的代碼複製出來,重新編寫一個驅動模塊apm-qyh.c,代碼如下。
  1 /*
  2  * bios-less APM driver for ARM Linux
  3  *  qiaoyihan
  4  *  adapted from the APM BIOS driver for Linux by Stephen Rothwell ([email protected])
  5  *
  6  */
  7 #include <linux/module.h>
  8 #include <linux/poll.h>
  9 #include <linux/slab.h>
 10 #include <linux/mutex.h>
 11 #include <linux/proc_fs.h>
 12 #include <linux/seq_file.h>
 13 #include <linux/miscdevice.h>
 14 #include <linux/apm_bios.h>
 15 #include <linux/capability.h>
 16 #include <linux/sched.h>
 17 #include <linux/apm-emulation.h>
 18 #include <linux/freezer.h>
 19 #include <linux/device.h>
 20 #include <linux/kernel.h>
 21 #include <linux/list.h>
 22 #include <linux/init.h>
 23 #include <linux/completion.h>
 24 #include <linux/kthread.h>
 25 #include <linux/delay.h>
 26 
 27 #include <asm/system.h>
 28 
 29 
 30 static const char driver_version[] = "1.13";    /* no spaces */
 31 
 32 /*
 33  * Compatibility cruft until the IPAQ people move over to the new
 34  * interface.
 35  */
 36 static void __apm_get_power_status(struct apm_power_info *info)
 37 {
 38     info->ac_line_status = 0x00;
 39     info->battery_status = 0x01;
 40     info->battery_flag   = 0x01;
 41     info->battery_life   = 30;
 42     info->time        = 135;
 43     info->units        = 1;
 44 }
 45 
 46 /*
 47  * This allows machines to provide their own "apm get power status" function.
 48  */
 49 void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status;
 50 
 51 /*
 52  * Arguments, with symbols from linux/apm_bios.h.
 53  *
 54  *   0) Linux driver version (this will change if format changes)
 55  *   1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
 56  *   2) APM flags from APM Installation Check (0x00):
 57  *    bit 0: APM_16_BIT_SUPPORT
 58  *    bit 1: APM_32_BIT_SUPPORT
 59  *    bit 2: APM_IDLE_SLOWS_CLOCK
 60  *    bit 3: APM_BIOS_DISABLED
 61  *    bit 4: APM_BIOS_DISENGAGED
 62  *   3) AC line status
 63  *    0x00: Off-line
 64  *    0x01: On-line
 65  *    0x02: On backup power (BIOS >= 1.1 only)
 66  *    0xff: Unknown
 67  *   4) Battery status
 68  *    0x00: High
 69  *    0x01: Low
 70  *    0x02: Critical
 71  *    0x03: Charging
 72  *    0x04: Selected battery not present (BIOS >= 1.2 only)
 73  *    0xff: Unknown
 74  *   5) Battery flag
 75  *    bit 0: High
 76  *    bit 1: Low
 77  *    bit 2: Critical
 78  *    bit 3: Charging
 79  *    bit 7: No system battery
 80  *    0xff: Unknown
 81  *   6) Remaining battery life (percentage of charge):
 82  *    0-100: valid
 83  *    -1: Unknown
 84  *   7) Remaining battery life (time units):
 85  *    Number of remaining minutes or seconds
 86  *    -1: Unknown
 87  *   8) min = minutes; sec = seconds
 88  */
 89 static int proc_apm_show(struct seq_file *m, void *v)
 90 {
 91     struct apm_power_info info;
 92     char *units;
 93 
 94     info.ac_line_status = 0xff;
 95     info.battery_status = 0xff;
 96     info.battery_flag   = 0xff;
 97     info.battery_life   = -1;
 98     info.time        = -1;
 99     info.units        = -1;
100 
101     if (apm_get_power_status)
102         apm_get_power_status(&info);
103 
104     switch (info.units) {
105     default:    units = "?";    break;
106     case 0:     units = "min";    break;
107     case 1:     units = "sec";    break;
108     }
109 
110     seq_printf(m, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
111              driver_version, APM_32_BIT_SUPPORT,
112              info.ac_line_status, info.battery_status,
113              info.battery_flag, info.battery_life,
114              info.time, units);
115 
116     return 0;
117 }
118 
119 static int proc_apm_open(struct inode *inode, struct file *file)
120 {
121     return single_open(file, proc_apm_show, NULL);
122 }
123 
124 static const struct file_operations apm_proc_fops = {
125     .owner        = THIS_MODULE,
126     .open        = proc_apm_open,
127     .read        = seq_read,
128     .llseek        = seq_lseek,
129     .release    = single_release,
130 };
131 
132 
133 static int __init apm_init(void)
134 {
135 
136     proc_create("apm", 0, NULL, &apm_proc_fops);
137     return 0;
138 }
139 
140 static void __exit apm_exit(void)
141 {
142     
143     remove_proc_entry("apm", NULL);
144 
145 }
146 
147 module_init(apm_init);
148 module_exit(apm_exit);
149 
150 MODULE_AUTHOR("qiaoyihan");
151 MODULE_DESCRIPTION("Power Status Management");
152 MODULE_LICENSE("GPL");
自己的操作在__apm_get_power_status函數裏實現,可以是AD檢測電量或其他電源管理芯片的操作,現在爲了測試只是給了一些固定的值。
發佈了52 篇原創文章 · 獲贊 16 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章