1*cf5a6c84SAndroid Build Coastguard Worker /* acpi.c - show power state
2*cf5a6c84SAndroid Build Coastguard Worker *
3*cf5a6c84SAndroid Build Coastguard Worker * Written by Isaac Dunham, 2013
4*cf5a6c84SAndroid Build Coastguard Worker *
5*cf5a6c84SAndroid Build Coastguard Worker * No standard.
6*cf5a6c84SAndroid Build Coastguard Worker
7*cf5a6c84SAndroid Build Coastguard Worker USE_ACPI(NEWTOY(acpi, "abctV", TOYFLAG_USR|TOYFLAG_BIN))
8*cf5a6c84SAndroid Build Coastguard Worker
9*cf5a6c84SAndroid Build Coastguard Worker config ACPI
10*cf5a6c84SAndroid Build Coastguard Worker bool "acpi"
11*cf5a6c84SAndroid Build Coastguard Worker default y
12*cf5a6c84SAndroid Build Coastguard Worker help
13*cf5a6c84SAndroid Build Coastguard Worker usage: acpi [-abctV]
14*cf5a6c84SAndroid Build Coastguard Worker
15*cf5a6c84SAndroid Build Coastguard Worker Show status of power sources and thermal devices.
16*cf5a6c84SAndroid Build Coastguard Worker
17*cf5a6c84SAndroid Build Coastguard Worker -a Show power adapters
18*cf5a6c84SAndroid Build Coastguard Worker -b Show batteries
19*cf5a6c84SAndroid Build Coastguard Worker -c Show cooling device state
20*cf5a6c84SAndroid Build Coastguard Worker -t Show temperatures
21*cf5a6c84SAndroid Build Coastguard Worker -V Show everything
22*cf5a6c84SAndroid Build Coastguard Worker */
23*cf5a6c84SAndroid Build Coastguard Worker
24*cf5a6c84SAndroid Build Coastguard Worker #define FOR_acpi
25*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
26*cf5a6c84SAndroid Build Coastguard Worker
read_int_at(int dirfd,char * name)27*cf5a6c84SAndroid Build Coastguard Worker static int read_int_at(int dirfd, char *name)
28*cf5a6c84SAndroid Build Coastguard Worker {
29*cf5a6c84SAndroid Build Coastguard Worker int fd, ret=0;
30*cf5a6c84SAndroid Build Coastguard Worker FILE *fil;
31*cf5a6c84SAndroid Build Coastguard Worker
32*cf5a6c84SAndroid Build Coastguard Worker if ((fd = openat(dirfd, name, O_RDONLY)) < 0) return -1;
33*cf5a6c84SAndroid Build Coastguard Worker if (!fscanf(fil = xfdopen(fd, "r"), "%d", &ret)) perror_exit_raw(name);
34*cf5a6c84SAndroid Build Coastguard Worker fclose(fil);
35*cf5a6c84SAndroid Build Coastguard Worker
36*cf5a6c84SAndroid Build Coastguard Worker return ret;
37*cf5a6c84SAndroid Build Coastguard Worker }
38*cf5a6c84SAndroid Build Coastguard Worker
acpi_callback(struct dirtree * tree)39*cf5a6c84SAndroid Build Coastguard Worker static int acpi_callback(struct dirtree *tree)
40*cf5a6c84SAndroid Build Coastguard Worker {
41*cf5a6c84SAndroid Build Coastguard Worker int dfd, fd, len, on, bat = 0, ac = 0;
42*cf5a6c84SAndroid Build Coastguard Worker char *cpath;
43*cf5a6c84SAndroid Build Coastguard Worker
44*cf5a6c84SAndroid Build Coastguard Worker errno = 0;
45*cf5a6c84SAndroid Build Coastguard Worker
46*cf5a6c84SAndroid Build Coastguard Worker if (*tree->name=='.') return 0;
47*cf5a6c84SAndroid Build Coastguard Worker if (!tree->parent) return DIRTREE_RECURSE|DIRTREE_SYMFOLLOW;
48*cf5a6c84SAndroid Build Coastguard Worker
49*cf5a6c84SAndroid Build Coastguard Worker if (0<=(dfd = open((cpath = dirtree_path(tree, 0)), O_RDONLY))) {
50*cf5a6c84SAndroid Build Coastguard Worker if ((fd = openat(dfd, "type", O_RDONLY)) < 0) goto done;
51*cf5a6c84SAndroid Build Coastguard Worker len = readall(fd, toybuf, sizeof(toybuf));
52*cf5a6c84SAndroid Build Coastguard Worker close(fd);
53*cf5a6c84SAndroid Build Coastguard Worker if (len<1) goto done;
54*cf5a6c84SAndroid Build Coastguard Worker
55*cf5a6c84SAndroid Build Coastguard Worker if (!strncmp(toybuf, "Battery", 7)) {
56*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(b) || !toys.optflags) {
57*cf5a6c84SAndroid Build Coastguard Worker int cap = 0, curr = 0, max = 0;
58*cf5a6c84SAndroid Build Coastguard Worker
59*cf5a6c84SAndroid Build Coastguard Worker if ((cap = read_int_at(dfd, "capacity"))<0) {
60*cf5a6c84SAndroid Build Coastguard Worker if ((max = read_int_at(dfd, "charge_full"))>0 ||
61*cf5a6c84SAndroid Build Coastguard Worker (max = read_int_at(dfd, "energy_full"))>0)
62*cf5a6c84SAndroid Build Coastguard Worker curr = read_int_at(dfd, "charge_now");
63*cf5a6c84SAndroid Build Coastguard Worker if (max>0 && curr>=0) cap = 100*curr/max;
64*cf5a6c84SAndroid Build Coastguard Worker }
65*cf5a6c84SAndroid Build Coastguard Worker if (cap>=0) printf("Battery %d: %d%%\n", bat++, cap);
66*cf5a6c84SAndroid Build Coastguard Worker }
67*cf5a6c84SAndroid Build Coastguard Worker } else if (FLAG(a) && (on = read_int_at(dfd, "online"))>=0)
68*cf5a6c84SAndroid Build Coastguard Worker printf("Adapter %d: %s-line\n", ac++, on ? "on" : "off");
69*cf5a6c84SAndroid Build Coastguard Worker done:
70*cf5a6c84SAndroid Build Coastguard Worker close(dfd);
71*cf5a6c84SAndroid Build Coastguard Worker }
72*cf5a6c84SAndroid Build Coastguard Worker free(cpath);
73*cf5a6c84SAndroid Build Coastguard Worker return 0;
74*cf5a6c84SAndroid Build Coastguard Worker }
75*cf5a6c84SAndroid Build Coastguard Worker
temp_callback(struct dirtree * tree)76*cf5a6c84SAndroid Build Coastguard Worker static int temp_callback(struct dirtree *tree)
77*cf5a6c84SAndroid Build Coastguard Worker {
78*cf5a6c84SAndroid Build Coastguard Worker int dfd, temp, therm = 0;
79*cf5a6c84SAndroid Build Coastguard Worker char *cpath;
80*cf5a6c84SAndroid Build Coastguard Worker
81*cf5a6c84SAndroid Build Coastguard Worker if (*tree->name=='.') return 0;
82*cf5a6c84SAndroid Build Coastguard Worker if (!tree->parent || !tree->parent->parent)
83*cf5a6c84SAndroid Build Coastguard Worker return DIRTREE_RECURSE|DIRTREE_SYMFOLLOW;
84*cf5a6c84SAndroid Build Coastguard Worker errno = 0;
85*cf5a6c84SAndroid Build Coastguard Worker
86*cf5a6c84SAndroid Build Coastguard Worker if (0<=(dfd = open((cpath = dirtree_path(tree, 0)), O_RDONLY))) {
87*cf5a6c84SAndroid Build Coastguard Worker if ((0 < (temp = read_int_at(dfd, "temp"))) || !errno) {
88*cf5a6c84SAndroid Build Coastguard Worker // some tempertures are in milli-C, some in deci-C
89*cf5a6c84SAndroid Build Coastguard Worker // reputedly some are in deci-K, but I have not seen them
90*cf5a6c84SAndroid Build Coastguard Worker if ((temp>=1000 || temp<=-1000) && !(temp%100)) temp /= 100;
91*cf5a6c84SAndroid Build Coastguard Worker printf("Thermal %d: %d.%d degrees C\n", therm++, temp/10, temp%10);
92*cf5a6c84SAndroid Build Coastguard Worker }
93*cf5a6c84SAndroid Build Coastguard Worker close(dfd);
94*cf5a6c84SAndroid Build Coastguard Worker }
95*cf5a6c84SAndroid Build Coastguard Worker free(cpath);
96*cf5a6c84SAndroid Build Coastguard Worker
97*cf5a6c84SAndroid Build Coastguard Worker return 0;
98*cf5a6c84SAndroid Build Coastguard Worker }
99*cf5a6c84SAndroid Build Coastguard Worker
cool_callback(struct dirtree * tree)100*cf5a6c84SAndroid Build Coastguard Worker static int cool_callback(struct dirtree *tree)
101*cf5a6c84SAndroid Build Coastguard Worker {
102*cf5a6c84SAndroid Build Coastguard Worker int dfd = 5, cur, max, cool = 0;
103*cf5a6c84SAndroid Build Coastguard Worker char *cpath;
104*cf5a6c84SAndroid Build Coastguard Worker
105*cf5a6c84SAndroid Build Coastguard Worker errno = 0;
106*cf5a6c84SAndroid Build Coastguard Worker memset(toybuf, 0, 257);
107*cf5a6c84SAndroid Build Coastguard Worker
108*cf5a6c84SAndroid Build Coastguard Worker if (*tree->name == '.') return 0;
109*cf5a6c84SAndroid Build Coastguard Worker if (!tree->parent) return DIRTREE_RECURSE|DIRTREE_SYMFOLLOW;
110*cf5a6c84SAndroid Build Coastguard Worker
111*cf5a6c84SAndroid Build Coastguard Worker if (0<=(dfd = open((cpath = dirtree_path(tree, &dfd)), O_RDONLY))) {
112*cf5a6c84SAndroid Build Coastguard Worker strcat(cpath, "/type");
113*cf5a6c84SAndroid Build Coastguard Worker if (readfile(cpath, toybuf, 256) && !errno) {
114*cf5a6c84SAndroid Build Coastguard Worker chomp(toybuf);
115*cf5a6c84SAndroid Build Coastguard Worker cur = read_int_at(dfd, "cur_state");
116*cf5a6c84SAndroid Build Coastguard Worker max = read_int_at(dfd, "max_state");
117*cf5a6c84SAndroid Build Coastguard Worker printf("Cooling %d: %s ", cool++, toybuf);
118*cf5a6c84SAndroid Build Coastguard Worker if (errno) printf("no state information\n");
119*cf5a6c84SAndroid Build Coastguard Worker else printf("%d of %d\n", cur, max);
120*cf5a6c84SAndroid Build Coastguard Worker }
121*cf5a6c84SAndroid Build Coastguard Worker close(dfd);
122*cf5a6c84SAndroid Build Coastguard Worker }
123*cf5a6c84SAndroid Build Coastguard Worker free(cpath);
124*cf5a6c84SAndroid Build Coastguard Worker
125*cf5a6c84SAndroid Build Coastguard Worker return 0;
126*cf5a6c84SAndroid Build Coastguard Worker }
127*cf5a6c84SAndroid Build Coastguard Worker
acpi_main(void)128*cf5a6c84SAndroid Build Coastguard Worker void acpi_main(void)
129*cf5a6c84SAndroid Build Coastguard Worker {
130*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(V)) toys.optflags = FLAG_a|FLAG_b|FLAG_c|FLAG_t;
131*cf5a6c84SAndroid Build Coastguard Worker if (!toys.optflags) toys.optflags = FLAG_b;
132*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(a)|FLAG(b)) dirtree_read("/sys/class/power_supply", acpi_callback);
133*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(t)) dirtree_read("/sys/class", temp_callback);
134*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(c)) dirtree_read("/sys/class/thermal", cool_callback);
135*cf5a6c84SAndroid Build Coastguard Worker }
136