summaryrefslogtreecommitdiff
path: root/library/power.cpp
Unidiff
Diffstat (limited to 'library/power.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--library/power.cpp226
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
37PowerStatusManager *PowerStatusManager::powerManager = 0;
38PowerStatus *PowerStatusManager::ps = 0;
39
40static bool haveProcApm = false;
41
42PowerStatusManager::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
53const 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
64bool 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
135void 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
187void 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