/**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* E-mail : see the 'copyright' file.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#include
#include "powermanager-draw.h"
#include "powermanager-struct.h"
#include "powermanager-common.h"
#include "powermanager-sys-class.h"
#define CD_BATTERY_DIR "/sys/class/power_supply"
/*POWER_SUPPLY_NAME=BAT1
POWER_SUPPLY_STATUS=Discharging
POWER_SUPPLY_PRESENT=1
POWER_SUPPLY_TECHNOLOGY=Li-ion
POWER_SUPPLY_CYCLE_COUNT=0
POWER_SUPPLY_VOLTAGE_MIN_DESIGN=11100000
POWER_SUPPLY_VOLTAGE_NOW=11100000
POWER_SUPPLY_CURRENT_NOW=0
POWER_SUPPLY_CHARGE_FULL_DESIGN=2200000
POWER_SUPPLY_CHARGE_FULL=2200000
POWER_SUPPLY_CHARGE_NOW=1760000
POWER_SUPPLY_MODEL_NAME=
POWER_SUPPLY_MANUFACTURER=DELL
POWER_SUPPLY_SERIAL_NUMBER=11
*/
static gboolean _find_battery_in_dir (const gchar *cBatteryPath)
{
// open the folder containing battery data.
GDir *dir = g_dir_open (cBatteryPath, 0, NULL);
if (dir == NULL)
{
cd_debug ("powermanager: no battery in %s",cBatteryPath );
return FALSE;
}
// parse the folder and search the battery files.
GString *sBatteryInfoFilePath = g_string_new ("");
gchar *cContent = NULL, *cPresentLine;
gsize length=0;
const gchar *cBatteryName;
gboolean bBatteryFound = FALSE;
do
{
cBatteryName = g_dir_read_name (dir); // usually "BAT0" or "BAT1".
if (cBatteryName == NULL)
break ;
// check the battery type.
g_string_printf (sBatteryInfoFilePath, "%s/%s/type", cBatteryPath, cBatteryName);
length=0;
cd_debug (" examen de la batterie '%s' ...", sBatteryInfoFilePath->str);
g_file_get_contents (sBatteryInfoFilePath->str, &cContent, &length, NULL);
if (cContent != NULL && strncmp (cContent, "Battery", 7) == 0) // there may be a \n at the end, so let's ignore it.
{
myData.cBatteryStateFilePath = g_strdup_printf ("%s/%s/uevent", cBatteryPath, cBatteryName);
bBatteryFound = TRUE; // get the capacity when we read the uevent for the first time.
cd_debug (" myData.cBatteryStateFilePath: %s", myData.cBatteryStateFilePath);
}
g_free (cContent);
}
while (! bBatteryFound);
g_dir_close (dir);
return bBatteryFound;
}
gboolean cd_find_battery_sys_class (void)
{
gboolean bBatteryFound = _find_battery_in_dir (CD_BATTERY_DIR);
return bBatteryFound;
}
#define _get_static_value(s, x) \
str = strstr (cContent, s);\
if (str) { \
str += strlen(s)+1;\
cr = strchr (str, '\n');\
if (cr) x = g_strndup (str, cr - str);\
else x = g_strdup (str); }
gboolean cd_get_stats_from_sys_class (void)
{
//\_______________ get the content of the stats file.
gchar *cContent = NULL;
gsize length=0;
GError *erreur = NULL;
g_file_get_contents (myData.cBatteryStateFilePath, &cContent, &length, &erreur);
if (erreur != NULL)
{
cd_warning ("powermanager : %s", erreur->message);
g_error_free(erreur);
erreur = NULL;
return FALSE;
}
g_return_val_if_fail (cContent != NULL, FALSE);
int k;
//\_______________ check 'on battery' state.
gchar *str = strstr (cContent, "STATUS");
g_return_val_if_fail (str != NULL, FALSE);
str += 7;
gboolean bOnBattery = (*str == 'D'); // "Discharging"
if (bOnBattery != myData.bOnBattery) // state changed
{
/**for (k = 0; k < PM_NB_VALUES; k ++) // reset the history.
myData.fRateHistory[k] = 0;
myData.iCurrentIndex = 0;
myData.iIndexMax = 0;*/
myData.iStatPercentageBegin = 0;
myData.iStatPercentage = 0;
myData.bOnBattery = bOnBattery;
}
//\_______________ check the battery presence.
str = strstr (cContent, "PRESENT");
g_return_val_if_fail (str != NULL, FALSE);
str += 8;
gboolean bBatteryPresent = (*str == '1');
if (bBatteryPresent != myData.bBatteryPresent) // the battery has just been inserted/removed.
{
myData.bBatteryPresent = bBatteryPresent;
if (! bBatteryPresent) // if the battery has been removed, we are obviously on the sector.
{
cd_debug ("la batterie a ete enlevee\n");
myData.bOnBattery = FALSE;
update_icon();
g_free (cContent);
return TRUE;
}
// reset the history.
cd_debug ("la batterie a ete connectee");
myData.iPrevTime = 0;
myData.iPrevPercentage = 0;
/**for (k = 0; k < PM_NB_VALUES; k ++)
myData.fRateHistory[k] = 0;
myData.iCurrentIndex = 0;
myData.iIndexMax = 0;*/
myData.iStatPercentageBegin = 0;
myData.iStatPercentage = 0;
}
//\_______________ get the current charge.
if (myData.iCapacity == 0) // not yet got
{
str = strstr (cContent, "CHARGE_FULL=");
g_return_val_if_fail (str != NULL, FALSE);
str += 12;
myData.iCapacity = atoi (str);
g_return_val_if_fail (myData.iCapacity != 0, FALSE);
// also get few other static params.
gchar *cr;
_get_static_value ("TECHNOLOGY", myData.cTechnology)
_get_static_value ("MANUFACTURER", myData.cVendor)
_get_static_value ("MODEL_NAME", myData.cModel)
str = strstr (cContent, "FULL_DESIGN");
if (str)
{
str += 12;
int iMaxCapacity = atoi (str);
if (iMaxCapacity != 0)
myData.fMaxAvailableCapacity = 100. * myData.iCapacity / iMaxCapacity;
}
}
str = strstr (cContent, "CHARGE_NOW");
g_return_val_if_fail (str != NULL, FALSE);
str += 11;
int iRemainingCapacity = atoi (str);
myData.iPercentage = 100. * iRemainingCapacity / myData.iCapacity;
cd_debug ("myData.iPercentage : %.2f%% (%d / %d)", (double)myData.iPercentage, iRemainingCapacity, myData.iCapacity);
if (myData.iPercentage > 100)
myData.iPercentage = 100;
if (myData.iPercentage < 0)
myData.iPercentage = 0.;
//\_______________ now compute the time.
myData.iTime = cd_estimate_time ();
g_free (cContent);
return (TRUE);
}