On Fri, Oct 10, 2014 at 11:24:15PM -0700, Isaac Dunham wrote: > 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
Any comments? (Denys?) Is it within scope? (I'd love to hear anything, even if it's "that belongs elsewhere". There's been a lot of silence...) Thanks, Isaac Dunham > From 0c0fad3ae324aa2383a9367715d205e41269d0c0 Mon Sep 17 00:00:00 2001 > From: Isaac Dunham <ibid...@gmail.com> > 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 busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox