acpi.c 3.7 KB

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