sm_sensor.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * Copyright (c) 2009 Willem Dijkstra
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * - Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * - Redistributions in binary form must reproduce the above
  12. * copyright notice, this list of conditions and the following
  13. * disclaimer in the documentation and/or other materials provided
  14. * with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  17. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  18. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  19. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  20. * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  21. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  22. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  26. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  27. * POSSIBILITY OF SUCH DAMAGE.
  28. *
  29. */
  30. /*
  31. * Get sensor data from the kernel via sysfs
  32. *
  33. * num : value
  34. *
  35. */
  36. #include "conf.h"
  37. #include <sys/types.h>
  38. #include <sys/stat.h>
  39. #include <ctype.h>
  40. #include <errno.h>
  41. #include <inttypes.h>
  42. #include <limits.h>
  43. #include <stdlib.h>
  44. #include <string.h>
  45. #include "error.h"
  46. #include "symon.h"
  47. #include "xmalloc.h"
  48. void
  49. privinit_sensor()
  50. {
  51. /* EMPTY */
  52. }
  53. void
  54. init_sensor(struct stream *st)
  55. {
  56. char buf[SYMON_MAX_OBJSIZE];
  57. struct stat pathinfo;
  58. char *name, *p;
  59. int32_t n;
  60. /* sensors can be identified as using
  61. *
  62. * - a relative path; /sys/class/hwmon[/hwmon0][/device]/${arg}_input is
  63. * then assumed: hwmon0/fan1 or fan1
  64. *
  65. * - the full path, e.g. /sys/class/hwmon/hwmon0/fan1 or
  66. * /sys/class/hwmon/hwmon0/device/fan1
  67. *
  68. * - the full path outside of sysfs, this may be necessary for hwmon probes
  69. * that need to some calculation before returning usable results,
  70. * e.g. /symon/fan1
  71. *
  72. * Note that _input is always appended to the sensor argument.
  73. */
  74. if (strlen(st->arg) < 1)
  75. fatal("sensor(): no valid argument");
  76. /* Determine the sensor type */
  77. if ((name = strrchr(st->arg, '/')))
  78. name += 1;
  79. else
  80. name = st->arg;
  81. if (sscanf(name, "fan%" SCNd32, &n) == 1)
  82. st->parg.sn.type = SENSOR_FAN;
  83. else if (sscanf(name, "in%" SCNd32, &n) == 1)
  84. st->parg.sn.type = SENSOR_IN;
  85. else if (sscanf(name, "temp%" SCNd32, &n) == 1)
  86. st->parg.sn.type = SENSOR_TEMP;
  87. else
  88. fatal("sensor(%.200s): '%s' is a unknown sensor type; expected fan/in/temp",
  89. st->arg, name);
  90. /* Find the sensor in sysfs */
  91. p = &st->parg.sn.path[0];
  92. if (st->arg[0] == '/') {
  93. snprintf(p, MAX_PATH_LEN - 1, "%s_input", st->arg);
  94. p[MAX_PATH_LEN - 1] = '\0';
  95. if (stat(p, &pathinfo) < 0)
  96. fatal("sensor(%.200s): could not find sensor at '%.200s'",
  97. st->arg, p);
  98. } else {
  99. snprintf(p, MAX_PATH_LEN - 1, "/sys/class/hwmon/hwmon0/%s_input", st->arg);
  100. p[MAX_PATH_LEN - 1] = '\0';
  101. if (stat(p, &pathinfo) < 0) {
  102. snprintf(p, MAX_PATH_LEN - 1, "/sys/class/hwmon/hwmon0/device/%s_input", st->arg);
  103. p[MAX_PATH_LEN - 1] = '\0';
  104. if (stat(p, &pathinfo) < 0)
  105. fatal("sensor(%.200s): could not be found in /sys/class/hwmon/hwmon0[/device]/%s_input",
  106. st->arg, st->arg);
  107. }
  108. }
  109. get_sensor(buf, sizeof(buf), st);
  110. info("started module sensor(%.200s)", st->arg);
  111. }
  112. int
  113. get_sensor(char *symon_buf, int maxlen, struct stream *st)
  114. {
  115. FILE *f;
  116. double t;
  117. if ((f = fopen(st->parg.sn.path, "r")) == NULL)
  118. fatal("sensor(%s): cannot access %.200s: %.200s",
  119. st->arg, st->parg.sn.path, strerror(errno));
  120. if (fscanf(f, "%lf", &t) < 0) {
  121. warning("sensor(%s): cannot read sensor value",
  122. st->arg);
  123. return 0;
  124. }
  125. if (fclose(f) < 0)
  126. warning("sensor(%s): cannot close '%.200s'",
  127. st->arg, st->parg.sn.path);
  128. switch (st->parg.sn.type) {
  129. case SENSOR_TEMP:
  130. case SENSOR_IN:
  131. t /= 1000.0;
  132. break;
  133. }
  134. return snpack(symon_buf, maxlen, st->arg, MT_SENSOR, t);
  135. }