diff options
author | Isaac Dunham <ibid.ag@gmail.com> | 2014-10-10 09:47:35 -0500 |
---|---|---|
committer | Isaac Dunham <ibid.ag@gmail.com> | 2014-10-10 09:47:35 -0500 |
commit | 26d8c3ccb0367b7e632d3819eb88c3cc349cc07b (patch) | |
tree | 92f2f4ffa4bb0ab0659028208e71049eaa5cc4ad /toys/other/acpi.c | |
parent | 3d56716d362d6a827c5f81029ac64c71b56a2f5c (diff) | |
download | toybox-26d8c3ccb0367b7e632d3819eb88c3cc349cc07b.tar.gz |
acpi: implement -ctV, fix recursion, plug a small leak
* acpi_callback had blindly assumed that a path of 26 chars or more was
the right depth; rely on depth from dirtree root
* acpi -c shows cooling device state
some backlights are set up so that they will report dimmer as higher,
but that's a hardware issue that can't be sanely worked around.
* acpi -t shows temperatures
this implementation will pick up fan, battery temperatures, etc.
(but currently not hwmon-type temperatures, or hdd temps;
acpi 1.7 does not measure these either)
we handle milli-C (typical) and deci-C (I've seen this on Qualcomm
batteries, and not yet anywhere else)
we do *not* handle deci-K yet
* acpi -V shows all sensors
* without saving the result of dirtree_path() to free later, we had
a slow leak.
all callbacks call this once, so save it in GLOBALS()
acpi -t happens to need this anyhow, though using openat()/readall()
instead of readfile() would work.
Diffstat (limited to 'toys/other/acpi.c')
-rw-r--r-- | toys/other/acpi.c | 78 |
1 files changed, 71 insertions, 7 deletions
diff --git a/toys/other/acpi.c b/toys/other/acpi.c index 1b31f313..c293e84c 100644 --- a/toys/other/acpi.c +++ b/toys/other/acpi.c @@ -4,18 +4,21 @@ * * No standard. -USE_ACPI(NEWTOY(acpi, "ab", TOYFLAG_USR|TOYFLAG_BIN)) +USE_ACPI(NEWTOY(acpi, "abctV", TOYFLAG_USR|TOYFLAG_BIN)) config ACPI bool "acpi" default y help - usage: acpi [-ab] + usage: acpi [-abctV] - Show status of power sources. + Show status of power sources and thermal devices. -a show power adapters -b show batteries + -c show cooling device state + -t show temperatures + -V show everything */ #define FOR_acpi @@ -24,6 +27,9 @@ config ACPI GLOBALS( int ac; int bat; + int therm; + int cool; + char *cpath; ) int read_int_at(int dirfd, char *name) @@ -46,10 +52,10 @@ int acpi_callback(struct dirtree *tree) if (tree->name[0]=='.') return 0; - if (strlen(dirtree_path(tree, NULL)) < 26) - return DIRTREE_RECURSE | DIRTREE_SYMFOLLOW; + if (!tree->parent) + return DIRTREE_RECURSE|DIRTREE_SYMFOLLOW; - if (0 <= (dfd = open(dirtree_path(tree, NULL), O_RDONLY))) { + if (0 <= (dfd = open((TT.cpath=dirtree_path(tree, NULL)), O_RDONLY))) { if ((fd = openat(dfd, "type", O_RDONLY)) < 0) goto done; len = readall(fd, toybuf, sizeof(toybuf)); close(fd); @@ -75,11 +81,69 @@ int acpi_callback(struct dirtree *tree) done: close(dfd); } + free(TT.cpath); + return 0; +} + +int temp_callback(struct dirtree *tree) +{ + int dfd, temp; + if (tree->name[0]=='.') return 0; + if (!tree->parent || !tree->parent->parent) + return DIRTREE_RECURSE|DIRTREE_SYMFOLLOW; + errno = 0; + + if (0 <= (dfd = open((TT.cpath=dirtree_path(tree, NULL)), O_RDONLY))) { + if ((0 < (temp = read_int_at(dfd, "temp"))) || !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", TT.therm++, temp/10, temp%10); + } + close(dfd); + } + free(TT.cpath); + return 0; +} + +int cool_callback(struct dirtree *tree) +{ + int dfd=5, cur, max; + errno = 0; + memset(toybuf, 0, sizeof(toybuf)); + + if (tree->name[0]=='.') return 0; + if (!tree->parent) return DIRTREE_RECURSE|DIRTREE_SYMFOLLOW; + + + if (0 <= (dfd = open((TT.cpath=dirtree_path(tree, &dfd)), O_RDONLY))) { + TT.cpath = strcat(TT.cpath, "/type"); + if (readfile(TT.cpath, toybuf, 256) && !errno) { + toybuf[strlen(toybuf) -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", TT.cool++, toybuf); + else printf("Cooling %d: %s %d of %d\n", TT.cool++, toybuf, cur, max); + } + close(dfd); + } + free(TT.cpath); return 0; } void acpi_main(void) { - dirtree_read("/sys/class/power_supply", acpi_callback); + if (toys.optflags & FLAG_V) + toys.optflags = FLAG_a|FLAG_b|FLAG_c|FLAG_t; + if (!toys.optflags) toys.optflags = FLAG_b; + if (toys.optflags & (FLAG_a|FLAG_b)) + dirtree_read("/sys/class/power_supply", acpi_callback); + if (toys.optflags & FLAG_t) + dirtree_read("/sys/class", temp_callback); + if (toys.optflags & FLAG_c) + dirtree_read("/sys/class/thermal", cool_callback); + } |