On several occasions I've wished for a tool that can show battery charge,
whether the power supply is working, and similar things.
Some time back I wrote the original version of this for toybox;
I just ported it to BusyBox.

If anyone could review it, I'd appreciate that.

Thanks,
Isaac Dunham
>From 0c0fad3ae324aa2383a9367715d205e41269d0c0 Mon Sep 17 00:00:00 2001
From: Isaac Dunham <[email protected]>
Date: Fri, 10 Oct 2014 22:53:36 -0700
Subject: [PATCH] Add "acpi" applet.

A tool to monitor power, temperature, and similar things.
Ported from toybox; subset clone of acpi-1.7.

function                                             old     new   delta
acpi_main                                              -     919    +919
.rodata                                           134270  134673    +403
read_int_at                                            -     129    +129
read_type_at                                           -     119    +119
packed_usage                                       29647   29721     +74
applet_names                                        2451    2456      +5
applet_main                                         1428    1432      +4
applet_nameofs                                       714     716      +2
------------------------------------------------------------------------------
(add/remove: 4/0 grow/shrink: 5/0 up/down: 1655/0)           Total: 1655 bytes
   text    data     bss     dec     hex filename
 887409    7512    1644  896565   dae35 busybox_old
 889140    7528    1644  898312   db508 busybox_unstripped
---
 miscutils/acpi.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 171 insertions(+)
 create mode 100644 miscutils/acpi.c

diff --git a/miscutils/acpi.c b/miscutils/acpi.c
new file mode 100644
index 0000000..f2a5601
--- /dev/null
+++ b/miscutils/acpi.c
@@ -0,0 +1,171 @@
+/* acpi.c - show power state
+ *
+ * Copyright 2013-2014 A.D., Isaac Dunham
+ *
+ * Based on toybox 0.5.0+ acpi.
+ * 
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+//config:config ACPI
+//config:      bool "acpi"
+//config:      default y
+//config:      select PLATFORM_LINUX
+//config:      help
+//config:        Show status of power sources and thermal devices.
+
+//applet:IF_ACPI(APPLET(acpi, BB_DIR_USR_BIN, BB_SUID_DROP))
+//kbuild:lib-$(CONFIG_ACPI) += acpi.o
+
+//usage:#define acpi_trivial_usage
+//usage:    "[-abctV]"
+//usage:#define acpi_full_usage "\n\n"
+//usage:    "Show status of power sources and thermal devices.\n"
+//usage:    "-a        show power adapters\n"
+//usage:    "-b        show batteries\n"
+//usage:    "-c        show cooling device state\n"
+//usage:    "-t        show temperatures\n"
+//usage:    "-V        show everything"
+
+
+#define FLAG_a 1
+#define FLAG_b 2
+#define FLAG_c 4
+#define FLAG_t 8
+#define FLAG_V 16
+
+#include "libbb.h"
+#include <glob.h>
+
+#define G_BUFSIZ 64
+struct globals {
+    int ac;
+    int bat;
+    int therm;
+    int cool;
+    char buf[G_BUFSIZ];
+} FIX_ALIASING;
+#define G (*(struct globals*)&bb_common_bufsiz1)
+
+static int read_int_at(int dirfd, const char *name)
+{
+    int fd, ret = 0;
+    FILE *fil;
+
+    if ((fd = openat(dirfd, name, O_RDONLY)) < 0)
+       return -1;
+    fscanf(fil = fdopen(fd, "r"), "%d", &ret);
+    fclose(fil);
+
+    return ret;
+}
+
+static char *read_type_at(int dirfd)
+{
+    int fd;
+    if ((fd = openat(dirfd, "type", O_RDONLY)) < 0)
+       return 0;
+    read(fd, G.buf, G_BUFSIZ-1);
+    close(fd);
+    if errno
+       return 0;
+    return G.buf;
+}
+
+int acpi_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int acpi_main(int argc UNUSED_PARAM, char **argv)
+{
+    glob_t files;
+    int dfd, on, cur, max, temp, i;
+    unsigned opts = getopt32(argv, "abctV");
+
+    if (opts & FLAG_V)
+       opts = FLAG_a | FLAG_b | FLAG_c | FLAG_t;
+    if (!opts)
+       opts = FLAG_b;
+    if (opts & (FLAG_a | FLAG_b)) {
+       glob("/sys/class/power_supply/*/", GLOB_NOSORT, NULL, &files);
+       for (i = 0; i < files.gl_pathc; i++) {
+           errno = 0;
+           if (0 <= (dfd = open(files.gl_pathv[i], O_RDONLY))) {
+               if (!read_type_at(dfd))
+                   goto ab_done;
+
+               if ((!strncmp(G.buf, "Battery", 7)) && (opts & FLAG_b)) {
+                   int cap = read_int_at(dfd, "capacity");
+
+                   if (cap < 0) {
+                       if ((max = read_int_at(dfd, "charge_full")) > 0)
+                           cur = read_int_at(dfd, "charge_now");
+                       else if ((max =
+                                 read_int_at(dfd, "energy_full")) > 0)
+                           cur = read_int_at(dfd, "energy_now");
+                       if (max > 0)
+                           cap = 100 * cur / max;
+                   }
+                   if (cap >= 0)
+                       printf("Battery %d: %d%%\n", G.bat++, cap);
+
+               } else if ((opts & FLAG_a)
+                          && ((on = read_int_at(dfd, "online")) >= 0)) {
+                   printf("Adapter %d: %s-line\n", G.ac++,
+                          (on ? "on" : "off"));
+               }
+             ab_done:
+               close(dfd);
+           }
+       }
+       globfree(&files);
+    }
+    if (opts & FLAG_t) {
+       glob("/sys/class/*/*/temp", GLOB_NOSORT, NULL, &files);
+       glob("/sys/class/*/*/temp*_input", GLOB_NOSORT | GLOB_APPEND, NULL,
+            &files);
+       for (i = 0; i < files.gl_pathc; i++) {
+           errno = 0;
+           if ((0 < (temp = read_int_at(AT_FDCWD, files.gl_pathv[i])))
+               || !errno) {
+               //some tempertures are in milli-C, some in deci-C
+               //reputedly some are in deci-K, but I have not seen them
+               if (((temp >= 1000) || (temp <= -1000))
+                   && (temp % 100 == 0))
+                   temp /= 100;
+               printf("Thermal %d: %d.%d degrees C\n", G.therm++,
+                      temp / 10, temp % 10);
+           }
+       }
+       globfree(&files);
+    }
+    if (opts & FLAG_c) {
+       glob("/sys/class/thermal/*/", GLOB_NOSORT, NULL, &files);
+       for (i = 0; i < files.gl_pathc; i++) {
+           errno = 0;
+           memset(G.buf, 0, 64);
+           if (0 <= (dfd = open(files.gl_pathv[i], O_RDONLY))) {
+               if (read_type_at(dfd) && !errno) {
+                   G.buf[strlen(G.buf) - 1] = 0;
+                   cur = read_int_at(dfd, "cur_state");
+                   max = read_int_at(dfd, "max_state");
+                   if (errno)
+                       printf("Cooling %d: %s no state information\n",
+                              G.cool++, G.buf);
+                   else
+                       printf("Cooling %d: %s %d of %d\n", G.cool++, G.buf,
+                              cur, max);
+               }
+               close(dfd);
+           }
+       }
+       globfree(&files);
+    }
+    return 0;
+}
-- 
2.1.2

_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to