aboutsummaryrefslogtreecommitdiff
path: root/toys/other/acpi.c
blob: 5caefeb28d18db97d405071f28c08ffd4a9ba20f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/* acpi.c - show power state
 * Written by Isaac Dunham, 2013
 * No standard.
USE_ACPI(NEWTOY(acpi, "ab", TOYFLAG_USR|TOYFLAG_BIN))

config ACPI
  bool "acpi"
  default n
  help
    usage: acpi [-ab]
    
    Show status of power sources.
    -a   show power adapters
    -b   show batteries
*/

#define FOR_acpi
#include "toys.h"

GLOBALS(
int ac;
int bat;
)

int read_int_at(int dirfd, char *name) {
  int fd, ret=0;
  if ((fd=openat(dirfd, name, O_RDONLY)) < 0)
    return -1;
  FILE * fil = xfdopen(fd, "r");
  fscanf(fil, "%d", &ret);
  fclose(fil);
  return ret;
}

int acpi_callback(struct dirtree *tree)
{
  errno = 0;

  if (tree->name[0]=='.')
    return 0;
  if (strlen(dirtree_path(tree, NULL)) < 26) {
    return (DIRTREE_RECURSE | DIRTREE_SYMFOLLOW);
  }
  int dfd=open(dirtree_path(tree, NULL), O_RDONLY);
  if (dfd > 0) {
    int fd;
    if ((fd = openat(dfd, "type", O_RDONLY)) < 0) {
      close(dfd);
      return 0;
    }
    read(fd, toybuf, 4096);
    close(fd);
    if (0 == strncmp(toybuf, "Battery", 7)) {
      if (toys.optflags & FLAG_b || (!toys.optflags)) {
        int cap = 0, curr = 0, max = 0;
        if ((cap = read_int_at(dfd, "capacity")) < 0) {
          if ((max = read_int_at(dfd, "charge_full")) > 0) {
            curr = read_int_at(dfd, "charge_now");
          } else if ((max = read_int_at(dfd, "energy_full")) > 0) {
            curr = read_int_at(dfd, "energy_now");
          }
          if (max > 0 && (curr >= 0))
            cap = 100 * curr / max;
        }
        if (cap >= 0) printf("Battery %d: %d%%\n", TT.bat++, cap);
      }
    } else {
      //ac
      if (toys.optflags & FLAG_a) {
        int on;
        if ((on = read_int_at(dfd, "online")) >= 0)
          printf("Adapter %d: %s-line\n", TT.ac++, (on ? "on" : "off"));
      }
    }
    close(dfd);
  }
  return 0;
}

void acpi_main(void)
{
  dirtree_read("/sys/class/power_supply", acpi_callback);
}