chiark / gitweb /
wip
[chiark-utils.git] / cprogs / xacpi-simple.c
index 034bc78df05c482dce54fb6edad7345a9a2577b8..c0810eaad93ce286a9a88097e0573c351acdf23b 100644 (file)
@@ -1,7 +1,8 @@
-todo
+/* todo
  power vs current
  Full
  old way of doing alarm
+*/
 
 /*
  * display outputs, per line:
@@ -90,7 +91,7 @@ struct fileinfo {
 };
 
 /*---------- structure of and results from /sys/class/power/... ----------*/
-/* variables thisbat_... are the results from readbattery();
+/* variables this_... are the results from readbattery();
  * if readbattery() succeeds the appropriate ones are all valid
  * and not VAL_NOTFOUND
  */
@@ -101,46 +102,58 @@ typedef struct batinfo_field {
   const char *enumarray[10];
 } batinfo_field;
 
-#define UEVENT_QUANTITY_FIELDS(f)                                      \
-  f(design_capacity,    BATTERY,  CHARGE_FULL_DESIGN ) /* uAh */       \
-  f(last_full_capacity, BATTERY,  CHARGE_FULL        ) /* uAh */       \
-  f(present_rate,       BATTERY,  CURRENT_NOW        ) /* uA  */       \
-  f(remaining_capacity, BATTERY,  CHARGE_NOW         ) /* uAh */       \
-  f(present,            BATTERY,  PRESENT            ) /* boolean */   \
-  f(online,             MAINS,    ONLINE             ) /* boolean */
+#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         )
+ /* ENERGY [mWh]; POWER [mW]; CHARGE [uAh]; CURRENT [uA] */
 
-#define UEVENT_ENUM_FIELDS(f)                                          \
-  f(state,   BATTERY,  STATUS,  "Discharging","Charging","Charged","Unknown" ) \
-  f(type,    BOTH,     TYPE,    "Mains",       "Battery"              )
+#define UEVENT_QTY_CHARGE(f,lle,llc,lr)                \
+  _(f##_energy,         BATTERY,  lle##_##lr ) \
+  _(f##_charge,         BATTERY,  llc##_##lr )
 
-#define CHGST_DISCHARGING 0 /* Reflects order in f(state,...) above     */
+#define UEVENT_QUANTITY_FIELDS(_)                                      \
+  BAT_QTYS(UEVENT_QTY_CHARGE)                                          \
+  _(present,            BATTERY,  PRESENT            ) /* boolean */   \
+  _(online,             MAINS,    ONLINE             ) /* boolean */
+
+#define UEVENT_ENUM_FIELDS(_)                                          \
+  _(state,   BATTERY,  STATUS,  "Discharging","Charging","Full","Unknown" ) \
+  _(type,    BOTH,     TYPE,    "Mains",       "Battery"              )
+
+#define CHGST_DISCHARGING 0 /* Reflects order in _(state,...) above     */
 #define CHGST_CHARGING    1 /* Also, much code assumes exactly          */
 #define CHGST_CHARGED     2 /* these three possible states.             */
 #define CHGST_UNKNOWN     3 /* these three possible states.             */
 #define CHGST_ERROR       8 /* Except that this one is an extra bit.    */
 
-#define TYPE_MAINS        0 /* Reflects order in f(type,...) above        */
+#define TYPE_MAINS        0 /* Reflects order in _(type,...) above        */
 #define TYPE_BATTERY      1 /* Also, much code assumes exactly these two  */
 #define TYPE_BOTH       100 /* Except this is a magic invalid value.      */
 
-#define SEPARATE_QUANTITY_FIELDS(f)            \
-  f(alarm,   BATTERY,  "alarm", "0", "1")
+#define SEPARATE_QUANTITY_FIELDS(_)            \
+  _(alarm,   BATTERY,  "alarm", "0", "1")
 
-#define ALL_FIELDS(f)                          \
-  UEVENT_QUANTITY_FIELDS(f)                    \
-  UEVENT_ENUM_FIELDS(f)                                \
-  SEPARATE_QUANTITY_FIELDS(f)
+#define ALL_FIELDS(_)                          \
+  UEVENT_QUANTITY_FIELDS(_)                    \
+  UEVENT_ENUM_FIELDS(_)                                \
+  SEPARATE_QUANTITY_FIELDS(_)
 
-#define ALL_QUANTITY_FIELDS(f)                 \
-  UEVENT_QUANTITY_FIELDS(f)                    \
-  SEPARATE_QUANTITY_FIELDS(f)
+#define ALL_QUANTITY_FIELDS(_)                 \
+  UEVENT_QUANTITY_FIELDS(_)                    \
+  SEPARATE_QUANTITY_FIELDS(_)
+
+#define ALL_VARS(_)                            \
+  ALL_FIELDS(_)                                        \
+  BAT_QTYS(_)
 
 #define F_VAR(f,...) \
-static value thisbat_##f;
-ALL_FIELDS(F_VAR)
+static value this_##f;
+ALL_VARS(F_VAR)
 
-#define Q_FLD(f,t,l)        { "POWER_SUPPLY_" #l, &thisbat_##f },
-#define E_FLD(f,t,l,vl...)  { "POWER_SUPPLY_" #l, &thisbat_##f, { vl } },
+#define Q_FLD(f,t,l)        { "POWER_SUPPLY_" #l, &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)
@@ -149,7 +162,7 @@ static const batinfo_field uevent_fields[]= {
 };
 
 #define S_FLD(f,t,fn,vl...)                                            \
-static const batinfo_field bif_##f = { 0, &thisbat_##f, { vl } };
+static const batinfo_field bif_##f = { 0, &this_##f, { vl } };
   SEPARATE_QUANTITY_FIELDS(S_FLD)
 
 #define S_FILE(f,t,fn,vl...) { fn, parse_separate, &bif_##f },
@@ -180,6 +193,12 @@ static int batfailf(const char *why) {
   return -1;
 }
 
+static int batfailc(const char *why) {
+  fprintf(stderr,"%s/%s: %s\n",
+         batdirname,batfilename, why);
+  return -1;
+}
+
 static int batfaile(const char *syscall, const char *target) {
   fprintf(stderr,"%s: failed to %s %s: %s\n",
          batdirname ? batdirname : "*", syscall, target, strerror(errno));
@@ -259,8 +278,8 @@ static int readbattery(void) { /* 0=>ok, -1=>couldn't */
   if (r) return batfaile("chdir",batdirname);
 
 #define V_NOTFOUND(f,...) \
-  thisbat_##f = VAL_NOTFOUND;
-ALL_FIELDS(V_NOTFOUND)
+  this_##f = VAL_NOTFOUND;
+ALL_VARS(V_NOTFOUND)
 
   for (cfile=files;
        (batfilename= cfile->filename);
@@ -291,14 +310,14 @@ ALL_FIELDS(V_NOTFOUND)
     batfile= 0;
   }
 
-  int needsfields_MAINS   = thisbat_type == TYPE_MAINS;
-  int needsfields_BATTERY = thisbat_type == TYPE_BATTERY;
+  int needsfields_MAINS   = this_type == TYPE_MAINS;
+  int needsfields_BATTERY = this_type == TYPE_BATTERY;
   int needsfields_BOTH    = 1;
 
   int missing = 0;
 
 #define V_NEEDED(f,t,...)                              \
-  if (needsfields_##t && thisbat_##f == VAL_NOTFOUND) {        \
+  if (needsfields_##t && this_##f == VAL_NOTFOUND) {   \
     fprintf(stderr,"%s: %s: not found\n",              \
            batdirname, #f);                            \
     missing++;                                         \
@@ -349,15 +368,28 @@ ALL_QUANTITY_FIELDS(Q_ZERO)
       break;
     }
 
-    if (thisbat_type == TYPE_BATTERY) {
-      if (!thisbat_present)
+    if (this_type == TYPE_BATTERY) {
+      if (!this_present)
        continue;
 
-      charging_mask |= 1u << thisbat_state;
+      charging_mask |= 1u << this_state;
 
-      if (thisbat_state == CHGST_DISCHARGING)
+      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;
+
+      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_TOTALISE(f,t,...)                    \