xref: /aosp_15_r20/external/toybox/toys/other/acpi.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
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