/* todo
- power vs current
- Full
old way of doing alarm
*/
#include <ctype.h>
#include <stdint.h>
#include <limits.h>
+#include <inttypes.h>
#include <sys/poll.h>
#include <sys/types.h>
#define TIMEOUT_ONERROR 3333 /* milliseconds */
static const char program_name[]= "xacpi-simple";
+static int debug;
/*---------- general utility stuff and declarations ----------*/
const char *enumarray[10];
} batinfo_field;
-#define BAT_QTYS(_) \
- _(design_capacity, ENERGY, CHARGE, FULL_DESIGN ) \
- _(last_full_capacity, ENERGY, CHARGE, FULL ) \
- _(remaining_capacity, ENERGY, CHARGE, NOW ) \
- _(present_rate, POWER, CURRENT, NOW )
+#define BAT_QTYS(_, _ec, EC_, PC_) \
+ _(design_capacity##_ec, BATTERY, EC_##FULL_DESIGN ) \
+ _(last_full_capacity##_ec, BATTERY, EC_##FULL ) \
+ _(remaining_capacity##_ec, BATTERY, EC_##NOW ) \
+ _(present_rate##_ec, BATTERY, PC_##NOW )
/* ENERGY [mWh]; POWER [mW]; CHARGE [uAh]; CURRENT [uA] */
-#define UEVENT_QTY_CHARGE(f,lle,llc,lr) \
- _(f##_energy, BATTERY, lle##_##lr ) \
- _(f##_charge, BATTERY, llc##_##lr )
+#define UEVENT_ESSENTIAL_QUANTITY_FIELDS(_) \
+ _(present, BATTERY, PRESENT /* bool */ ) \
+ _(online, MAINS, ONLINE /* bool */ )
-#define UEVENT_QUANTITY_FIELDS(_) \
- BAT_QTYS(UEVENT_QTY_CHARGE) \
- _(present, BATTERY, PRESENT ) /* boolean */ \
- _(online, MAINS, ONLINE ) /* boolean */
+#define UEVENT_FUNKY_QUANTITY_FIELDS(_) \
+ BAT_QTYS(_,_energy,ENERGY_,POWER_) \
+ BAT_QTYS(_,_charge,CHARGE_,CURRENT_)
+
+#define UEVENT_OPTIONAL_QUANTITY_FIELDS(_) \
+ _(voltage, BATTERY, VOLTAGE_NOW /* uV */ )
#define UEVENT_ENUM_FIELDS(_) \
_(state, BATTERY, STATUS, "Discharging","Charging","Full","Unknown" ) \
#define SEPARATE_QUANTITY_FIELDS(_) \
_(alarm, BATTERY, "alarm", "0", "1")
-#define ALL_FIELDS(_) \
- UEVENT_QUANTITY_FIELDS(_) \
+
+#define ALL_DIRECT_VARS(_) \
+ UEVENT_ESSENTIAL_QUANTITY_FIELDS(_) \
+ UEVENT_FUNKY_QUANTITY_FIELDS(_) \
+ UEVENT_OPTIONAL_QUANTITY_FIELDS(_) \
UEVENT_ENUM_FIELDS(_) \
SEPARATE_QUANTITY_FIELDS(_)
-#define ALL_QUANTITY_FIELDS(_) \
- UEVENT_QUANTITY_FIELDS(_) \
+#define ALL_VARS(_) \
+ ALL_DIRECT_VARS(_) \
+ BAT_QTYS(_,,,)
+
+#define ALL_NEEDED_FIELDS(_) \
+ UEVENT_ESSENTIAL_QUANTITY_FIELDS(_) \
+ UEVENT_ENUM_FIELDS(_) \
SEPARATE_QUANTITY_FIELDS(_)
-#define ALL_VARS(_) \
- ALL_FIELDS(_) \
- BAT_QTYS(_)
+#define ALL_PLAIN_ACCUMULATE_FIELDS(_) \
+ UEVENT_ESSENTIAL_QUANTITY_FIELDS(_) \
+ UEVENT_ENUM_FIELDS(_) \
+ SEPARATE_QUANTITY_FIELDS(_)
+
+#define ALL_ACCUMULATE_FIELDS(_) \
+ ALL_PLAIN_ACCUMULATE_FIELDS(_) \
+ BAT_QTYS(_,,,)
+
#define F_VAR(f,...) \
static value this_##f;
#define E_FLD(f,t,l,vl...) { "POWER_SUPPLY_" #l, &this_##f, { vl } },
static const batinfo_field uevent_fields[]= {
- UEVENT_QUANTITY_FIELDS(Q_FLD)
+ UEVENT_ESSENTIAL_QUANTITY_FIELDS(Q_FLD)
+ UEVENT_FUNKY_QUANTITY_FIELDS(Q_FLD)
+ UEVENT_OPTIONAL_QUANTITY_FIELDS(Q_FLD)
UEVENT_ENUM_FIELDS(E_FLD)
{ 0 }
};
batfile= 0;
}
+ if (debug) {
+ printf("%s:\n",batdirname);
+#define V_PRINT(f,...) \
+ printf(" %-30s = %20"PRId64"\n", #f, (int64_t)this_##f);
+ALL_DIRECT_VARS(V_PRINT)
+ }
+
int needsfields_MAINS = this_type == TYPE_MAINS;
int needsfields_BATTERY = this_type == TYPE_BATTERY;
int needsfields_BOTH = 1;
batdirname, #f); \
missing++; \
}
-ALL_FIELDS(V_NEEDED)
+ALL_NEEDED_FIELDS(V_NEEDED)
if (missing) return -1;
#define Q_VAR(f,t,...) \
static double total_##f;
- ALL_QUANTITY_FIELDS(Q_VAR)
+ ALL_ACCUMULATE_FIELDS(Q_VAR)
static void acquiredata(void) {
DIR *di;
#define Q_ZERO(f,t,...) \
total_##f= 0;
-ALL_QUANTITY_FIELDS(Q_ZERO)
+ALL_ACCUMULATE_FIELDS(Q_ZERO)
r = chdir_base();
if (r) goto bad;
charging_mask |= 1u << this_state;
+#define QTY_SUPPLIED(f,...) this_##f != VAL_NOTFOUND &&
+#define QTY_USE_ENERGY(f,...) this_##f = this_##f##_energy;
+#define QTY_USE_CHARGE(f,...) this_##f = this_##f##_charge;
+
+ double funky_multiplier;
+ if (BAT_QTYS(QTY_SUPPLIED,_energy,,) 1) {
+ if (debug) printf(" using energy\n");
+ BAT_QTYS(QTY_USE_ENERGY,,,);
+ funky_multiplier = 1.0;
+ } else if (BAT_QTYS(QTY_SUPPLIED,_charge,,)
+ this_voltage != VAL_NOTFOUND) {
+ if (debug) printf(" using charge\n");
+ BAT_QTYS(QTY_USE_CHARGE,,,);
+ funky_multiplier = this_voltage * 1e-6;
+ } else {
+ batfailc("neither complete set of energy nor charge");
+ continue;
+ }
if (this_state == CHGST_DISCHARGING)
/* negate it */
- total_present_rate -= 2.0 * thisbat_present_rate;
-
-#define QTY_ENERGY_SUPPLIED(f,...) this_##f##_energy != V_NOTFOUND &&
-#define QTY_ENERGY_USE(f,...) this_##f = this_##f##_energy;
-#define QTY_CHARGE_SUPPLIED(f,...) this_##f##_charge != V_NOTFOUND &&
-#define QTY_CHARGE_USE(f,...) this_##f = this_##f##_charge;
+ total_present_rate -= 2.0 * this_present_rate * funky_multiplier;
- if (BAT_QTYS(QTY_ENERGY_SUPPLIED) 1) {
- BAT_QTYS(QTY_ENERGY_USE);
- } else if (BAT_QTYS(QTY_CHARGE_SUPPLIED) 1) {
- BAT_QTYS(QTY_CHARGE_USE);
- } else {
- return batfailc("neither complete set of energy nor charge");
- }
+#define Q_ACCUMULATE_FUNKY(f,...) \
+ total_##f += this_##f * funky_multiplier;
+BAT_QTYS(Q_ACCUMULATE_FUNKY,,,)
}
-#define Q_TOTALISE(f,t,...) \
- if (thisbat_type == TYPE_##t) \
- total_##f += thisbat_##f;
-ALL_QUANTITY_FIELDS(Q_TOTALISE)
+#define Q_ACCUMULATE_PLAIN(f,t,...) \
+ if (this_type == TYPE_##t) \
+ total_##f += this_##f;
+ALL_PLAIN_ACCUMULATE_FIELDS(Q_ACCUMULATE_PLAIN)
+
}
closedir(di);
+ printf("TOTAL:\n");
+#define T_PRINT(f,...) \
+ printf(" %-30s = %20.6f\n", #f, total_##f);
+BAT_QTYS(T_PRINT,,,)
+ALL_PLAIN_ACCUMULATE_FIELDS(T_PRINT)
+
if (total_design_capacity < 0.5)
total_design_capacity= 1.0;
#define S(s) ((char*)(s))
static const XrmOptionDescRec optiontable[]= {
+ { S("-debug"), S("*debug"), XrmoptionIsArg },
{ S("-display"), S("*display"), XrmoptionSepArg },
{ S("-geometry"), S("*geometry"), XrmoptionSepArg },
#define GC(g)
if (argc>1) badusage();
+ debug= !!getresource("debug");
+
disp= XOpenDisplay(getresource("display"));
if (!disp) fail("could not open display");