1 /**
2 * This file is a part of the Cairo-Dock project
3 *
4 * Copyright : (C) see the 'copyright' file.
5 * E-mail : see the 'copyright' file.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <math.h>
21 #include <string.h>
22 #include <dirent.h>
23 #include <dbus/dbus-glib.h>
24
25 #include "powermanager-draw.h"
26 #include "powermanager-struct.h"
27 #include "powermanager-common.h"
28 #include "powermanager-proc-acpi.h"
29
30 #define CD_BATTERY_DIR "/proc/acpi/battery"
31 //#define CD_BATTERY_DIR "/home/fab/proc/acpi/battery"
32
33 /*present: yes
34 capacity state: ok
35 charging state: discharging
36 present rate: 15000 mW
37 remaining capacity: 47040 mWh
38 present voltage: 15000 mV*/
39
_find_battery_in_dir(const gchar * cBatteryPath)40 static gboolean _find_battery_in_dir (const gchar *cBatteryPath)
41 {
42 // open the folder containing battery data.
43 GDir *dir = g_dir_open (cBatteryPath, 0, NULL);
44 if (dir == NULL)
45 {
46 cd_debug ("powermanager: no battery in %s",cBatteryPath );
47 return FALSE;
48 }
49
50 // parse the folder and search the battery files.
51 GString *sBatteryInfoFilePath = g_string_new ("");
52 gchar *cContent = NULL;
53 gsize length=0;
54 const gchar *cBatteryName;
55 gboolean bBatteryFound = FALSE;
56 do
57 {
58 cBatteryName = g_dir_read_name (dir); // usually "BAT0".
59 if (cBatteryName == NULL)
60 break ;
61
62 // check the battery info.
63 g_string_printf (sBatteryInfoFilePath, "%s/%s/info", cBatteryPath, cBatteryName);
64 length=0;
65 cd_debug (" examen de la batterie '%s' ...", sBatteryInfoFilePath->str);
66 g_file_get_contents (sBatteryInfoFilePath->str, &cContent, &length, NULL);
67 if (cContent != NULL)
68 {
69 gchar *str = strchr (cContent, '\n'); // first line: "present: yes"
70 if (str != NULL)
71 {
72 gchar *str2 = strchr (str+1, ':');
73 if (str2 != NULL)
74 {
75 str2 ++;
76 myData.iCapacity = atoi (str2);
77
78 gchar *str3 = strchr (str2, ':');
79 if (str3 != NULL) // prefer the last full capacity if available.
80 {
81 str3 ++;
82 myData.iCapacity = atoi (str3);
83 }
84
85 cd_debug ("Capacity : %d mWsh", myData.iCapacity);
86 myData.cBatteryStateFilePath = g_strdup_printf ("%s/%s/state", cBatteryPath, cBatteryName);
87 bBatteryFound = TRUE;
88 }
89 }
90 g_free (cContent);
91 }
92 }
93 while (! bBatteryFound);
94 g_dir_close (dir);
95 return bBatteryFound;
96 }
cd_find_battery_proc_acpi(void)97 gboolean cd_find_battery_proc_acpi (void)
98 {
99 gboolean bBatteryFound = _find_battery_in_dir (CD_BATTERY_DIR);
100 return bBatteryFound;
101 }
102
103
104 #define go_to_next_line \
105 cCurLine = strchr (cCurVal, '\n'); \
106 g_return_val_if_fail (cCurLine != NULL, FALSE); \
107 cCurLine ++; \
108 cCurVal = cCurLine;
109
110 #define jump_to_value \
111 cCurVal = strchr (cCurLine, ':'); \
112 g_return_val_if_fail (cCurVal != NULL, FALSE); \
113 cCurVal ++; \
114 while (*cCurVal == ' ') \
115 cCurVal ++;
116
cd_get_stats_from_proc_acpi(void)117 gboolean cd_get_stats_from_proc_acpi (void)
118 {
119 //\_______________ get the content of the stats file.
120 gchar *cContent = NULL;
121 gsize length=0;
122 GError *erreur = NULL;
123 g_file_get_contents (myData.cBatteryStateFilePath, &cContent, &length, &erreur);
124 if (erreur != NULL)
125 {
126 cd_warning ("powermanager : %s", erreur->message);
127 g_error_free(erreur);
128 erreur = NULL;
129 return FALSE;
130 }
131 g_return_val_if_fail (cContent != NULL, FALSE);
132
133 gchar *cCurLine = cContent, *cCurVal = cContent;
134
135 //\_______________ check the battery presence.
136 jump_to_value // "present: yes"
137 gboolean bBatteryPresent = (*cCurVal == 'y');
138 if (bBatteryPresent != myData.bBatteryPresent) // the battery has just been inserted/removed.
139 {
140 myData.bBatteryPresent = bBatteryPresent;
141 if (! bBatteryPresent) // if the battery has been removed, we are obviously on the sector.
142 {
143 cd_debug ("la batterie a ete enlevee\n");
144 myData.bOnBattery = FALSE;
145 update_icon();
146 g_free (cContent);
147 return TRUE;
148 }
149
150 // reset the history.
151 cd_debug ("la batterie a ete connectee\n");
152 myData.iPrevTime = 0;
153 myData.iPrevPercentage = 0;
154 /**for (k = 0; k < PM_NB_VALUES; k ++)
155 myData.fRateHistory[k] = 0;
156 myData.iCurrentIndex = 0;
157 myData.iIndexMax = 0;*/
158 myData.iStatPercentageBegin = 0;
159 myData.iStatPercentage = 0;
160 }
161
162 go_to_next_line // -> "capacity state: ok"
163
164 go_to_next_line // -> "charging state: discharging"
165
166 //\_______________ check 'on battery' state.
167 jump_to_value
168 gboolean bOnBattery = (*cCurVal == 'd'); // "discharging"
169 if (bOnBattery != myData.bOnBattery) // state changed
170 {
171 /**for (k = 0; k < PM_NB_VALUES; k ++) // reset the history.
172 myData.fRateHistory[k] = 0;
173 myData.iCurrentIndex = 0;
174 myData.iIndexMax = 0;*/
175 myData.iStatPercentageBegin = 0;
176 myData.iStatPercentage = 0;
177 myData.bOnBattery = bOnBattery;
178 }
179
180 go_to_next_line // -> present rate: 15000 mW
181
182 //\_______________ get the current charge and rate (this one can be 0 if not available).
183 jump_to_value
184 // double fPresentRate = atoi (cCurVal); // 15000 mW OU 1400 mA
185
186 /*cCurVal ++;
187 while (*cCurVal != ' ')
188 cCurVal ++;
189 while (*cCurVal == ' ')
190 cCurVal ++;
191 if (*cCurVal != 'm')
192 cd_warning ("PowerManager : expecting mA or mW as the present rate unit");
193 cCurVal ++;
194 if (*cCurVal == 'W')
195 bWatt = TRUE;
196 else if (*cCurVal == 'A')
197 bWatt = FALSE;
198 else
199 cd_warning ("PowerManager : expecting A or W as the present rate unit");*/
200
201 go_to_next_line // -> "remaining capacity: 47040 mWh"
202
203 jump_to_value
204 int iRemainingCapacity = atoi (cCurVal); // 47040 mWh
205
206 /**go_to_next_line // -> "present voltage: 15000 mV"
207
208 jump_to_value
209 int iPresentVoltage = atoi (cCurVal); // 15000 mV
210 */
211 myData.iPercentage = 100. * iRemainingCapacity / myData.iCapacity;
212 cd_debug ("myData.iPercentage : %.2f%% (%d / %d)", (double)myData.iPercentage, iRemainingCapacity, myData.iCapacity);
213 if (myData.iPercentage > 100)
214 myData.iPercentage = 100;
215 if (myData.iPercentage < 0)
216 myData.iPercentage = 0.;
217
218 //\_______________ now compute the time.
219 myData.iTime = cd_estimate_time ();
220
221 //cd_message ("PowerManager : On Battery:%d ; iCapacity:%dmWh ; iRemainingCapacity:%dmWh ; fPresentRate:%.2fmW ; iPresentVoltage:%dmV", myData.bOnBattery, myData.iCapacity, iRemainingCapacity, fPresentRate, iPresentVoltage);
222 g_free (cContent);
223 return (TRUE);
224 }
225