-rw-r--r-- | library/power.cpp | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/library/power.cpp b/library/power.cpp new file mode 100644 index 0000000..990ff62 --- a/dev/null +++ b/library/power.cpp | |||
@@ -0,0 +1,226 @@ | |||
1 | /********************************************************************** | ||
2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. | ||
3 | ** | ||
4 | ** This file is part of Qtopia Environment. | ||
5 | ** | ||
6 | ** This file may be distributed and/or modified under the terms of the | ||
7 | ** GNU General Public License version 2 as published by the Free Software | ||
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | ||
9 | ** packaging of this file. | ||
10 | ** | ||
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | ||
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
13 | ** | ||
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | ||
15 | ** | ||
16 | ** Contact info@trolltech.com if any conditions of this licensing are | ||
17 | ** not clear to you. | ||
18 | ** | ||
19 | **********************************************************************/ | ||
20 | |||
21 | #include "power.h" | ||
22 | |||
23 | #ifdef QT_QWS_CUSTOM | ||
24 | #include "custom.h" | ||
25 | #endif | ||
26 | |||
27 | #include <unistd.h> | ||
28 | #include <stdlib.h> | ||
29 | #include <stdio.h> | ||
30 | #include <fcntl.h> | ||
31 | #include <sys/ioctl.h> | ||
32 | |||
33 | #ifdef QT_QWS_IPAQ_NO_APM | ||
34 | #include <linux/h3600_ts.h> | ||
35 | #endif | ||
36 | |||
37 | PowerStatusManager *PowerStatusManager::powerManager = 0; | ||
38 | PowerStatus *PowerStatusManager::ps = 0; | ||
39 | |||
40 | static bool haveProcApm = false; | ||
41 | |||
42 | PowerStatusManager::PowerStatusManager() | ||
43 | { | ||
44 | powerManager = this; | ||
45 | ps = new PowerStatus; | ||
46 | FILE *f = fopen("/proc/apm", "r"); | ||
47 | if ( f ) { | ||
48 | fclose(f); | ||
49 | haveProcApm = TRUE; | ||
50 | } | ||
51 | } | ||
52 | |||
53 | const PowerStatus &PowerStatusManager::readStatus() | ||
54 | { | ||
55 | if ( !powerManager ) | ||
56 | (void)new PowerStatusManager; | ||
57 | |||
58 | powerManager->getStatus(); | ||
59 | |||
60 | return *ps; | ||
61 | } | ||
62 | |||
63 | // Standard /proc/apm reader | ||
64 | bool PowerStatusManager::getProcApmStatus( int &ac, int &bs, int &bf, int &pc, int &sec ) | ||
65 | { | ||
66 | bool ok = false; | ||
67 | |||
68 | ac = 0xff; | ||
69 | bs = 0xff; | ||
70 | bf = 0xff; | ||
71 | pc = -1; | ||
72 | sec = -1; | ||
73 | |||
74 | FILE *f = fopen("/proc/apm", "r"); | ||
75 | if ( f ) { | ||
76 | //I 1.13 1.2 0x02 0x00 0xff 0xff 49% 147 sec | ||
77 | char u; | ||
78 | fscanf(f, "%*[^ ] %*d.%*d 0x%*x 0x%x 0x%x 0x%x %d%% %i %c", | ||
79 | &ac, &bs, &bf, &pc, &sec, &u); | ||
80 | fclose(f); | ||
81 | switch ( u ) { | ||
82 | case 'm': sec *= 60; | ||
83 | case 's': break; // ok | ||
84 | default: sec = -1; // unknown | ||
85 | } | ||
86 | |||
87 | // extract data | ||
88 | switch ( bs ) { | ||
89 | case 0x00: | ||
90 | ps->bs = PowerStatus::High; | ||
91 | break; | ||
92 | case 0x01: | ||
93 | ps->bs = PowerStatus::Low; | ||
94 | break; | ||
95 | case 0x7f: | ||
96 | ps->bs = PowerStatus::VeryLow; | ||
97 | break; | ||
98 | case 0x02: | ||
99 | ps->bs = PowerStatus::Critical; | ||
100 | break; | ||
101 | case 0x03: | ||
102 | ps->bs = PowerStatus::Charging; | ||
103 | break; | ||
104 | case 0x04: | ||
105 | ps->bs = PowerStatus::NotPresent; | ||
106 | break; | ||
107 | } | ||
108 | |||
109 | switch ( ac ) { | ||
110 | case 0x00: | ||
111 | ps->ac = PowerStatus::Offline; | ||
112 | break; | ||
113 | case 0x01: | ||
114 | ps->ac = PowerStatus::Online; | ||
115 | break; | ||
116 | case 0x02: | ||
117 | ps->ac = PowerStatus::Backup; | ||
118 | break; | ||
119 | } | ||
120 | |||
121 | if ( pc > 100 ) | ||
122 | pc = -1; | ||
123 | |||
124 | ps->percentRemain = pc; | ||
125 | ps->secsRemain = sec; | ||
126 | |||
127 | ok = true; | ||
128 | } | ||
129 | |||
130 | return ok; | ||
131 | } | ||
132 | |||
133 | #ifdef QT_QWS_CUSTOM | ||
134 | |||
135 | void PowerStatusManager::getStatus() | ||
136 | { | ||
137 | int ac, bs, bf, pc, sec; | ||
138 | ps->percentAccurate = TRUE; // not for long... | ||
139 | |||
140 | if ( haveProcApm && getProcApmStatus( ac, bs, bf, pc, sec ) ) { | ||
141 | // special case | ||
142 | if ( bs == 0x7f ) | ||
143 | ps->bs = PowerStatus::VeryLow; | ||
144 | pc = -1; // fake percentage | ||
145 | if ( pc < 0 ) { | ||
146 | switch ( bs ) { | ||
147 | case 0x00: ps->percentRemain = 100; break; // High | ||
148 | case 0x01: ps->percentRemain = 30; break; // Low | ||
149 | case 0x7f: ps->percentRemain = 10; break; // Very Low | ||
150 | case 0x02: ps->percentRemain = 5; break; // Critical | ||
151 | case 0x03: ps->percentRemain = -1; break; // Charging | ||
152 | } | ||
153 | ps->percentAccurate = FALSE; | ||
154 | } | ||
155 | } | ||
156 | |||
157 | char *device = "/dev/apm_bios"; | ||
158 | int fd = ::open (device, O_WRONLY); | ||
159 | if ( fd >= 0 ) { | ||
160 | int bbat_status = ioctl( fd, APM_IOC_BATTERY_BACK_CHK, 0 ); | ||
161 | switch ( bbat_status ) { | ||
162 | case 0x00: | ||
163 | ps->bbs = PowerStatus::High; | ||
164 | break; | ||
165 | case 0x01: | ||
166 | ps->bbs = PowerStatus::Low; | ||
167 | break; | ||
168 | case 0x7f: | ||
169 | ps->bbs = PowerStatus::VeryLow; | ||
170 | break; | ||
171 | case 0x02: | ||
172 | ps->bbs = PowerStatus::Critical; | ||
173 | break; | ||
174 | case 0x03: | ||
175 | ps->bbs = PowerStatus::Charging; | ||
176 | break; | ||
177 | case 0x04: | ||
178 | ps->bbs = PowerStatus::NotPresent; | ||
179 | break; | ||
180 | } | ||
181 | ::close(fd); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | #else | ||
186 | |||
187 | void PowerStatusManager::getStatus() | ||
188 | { | ||
189 | bool usedApm = FALSE; | ||
190 | |||
191 | ps->percentAccurate = TRUE; | ||
192 | |||
193 | // Some iPAQ kernel builds don't have APM. If this is not the case we | ||
194 | // save ourselves an ioctl by testing if /proc/apm exists in the | ||
195 | // constructor and we use /proc/apm instead | ||
196 | int ac, bs, bf, pc, sec; | ||
197 | if ( haveProcApm ) | ||
198 | usedApm = getProcApmStatus( ac, bs, bf, pc, sec ); | ||
199 | |||
200 | if ( !usedApm ) { | ||
201 | #ifdef QT_QWS_IPAQ_NO_APM | ||
202 | int fd; | ||
203 | int err; | ||
204 | struct bat_dev batt_info; | ||
205 | |||
206 | memset(&batt_info, 0, sizeof(batt_info)); | ||
207 | |||
208 | fd = ::open("/dev/ts",O_RDONLY); | ||
209 | if( fd < 0 ) | ||
210 | return; | ||
211 | |||
212 | ioctl(fd, GET_BATTERY_STATUS, &batt_info); | ||
213 | ac_status = batt_info.ac_status; | ||
214 | ps->percentRemain = ( 425 * batt_info.batt1_voltage ) / 1000 - 298; // from h3600_ts.c | ||
215 | ps->secsRemain = -1; // seconds is bogus on iPAQ | ||
216 | ::close (fd); | ||
217 | #else | ||
218 | ps->percentRemain = 100; | ||
219 | ps->secsRemain = -1; | ||
220 | ps->percentAccurate = FALSE; | ||
221 | #endif | ||
222 | } | ||
223 | } | ||
224 | |||
225 | #endif | ||
226 | |||