sm_sensor.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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 <errno.h>
  40. #include <limits.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include <ctype.h>
  44. #include "error.h"
  45. #include "symon.h"
  46. #include "xmalloc.h"
  47. void
  48. privinit_sensor()
  49. {
  50. /* EMPTY */
  51. }
  52. void
  53. init_sensor(struct stream *st)
  54. {
  55. char buf[SYMON_MAX_OBJSIZE];
  56. struct stat pathinfo;
  57. char *name, *p;
  58. int n;
  59. /* sensors can be identified as using
  60. *
  61. * - a relative path; /sys/class/hwmon[/hwmon0][/device]/${arg}_input is
  62. * then assumed: hwmon0/fan1 or fan1
  63. *
  64. * - the full path, e.g. /sys/class/hwmon/hwmon0/fan1 or
  65. * /sys/class/hwmon/hwmon0/device/fan1
  66. *
  67. * - the full path outside of sysfs, this may be necessary for hwmon probes
  68. * that need to some calculation before returning usable results,
  69. * e.g. /symon/fan1
  70. *
  71. * Note that _input is always appended to the sensor argument.
  72. */
  73. if (strlen(st->arg) < 1)
  74. fatal("sensor(): no valid argument");
  75. /* Determine the sensor type */
  76. if ((name = strrchr(st->arg, '/')))
  77. name += 1;
  78. else
  79. name = st->arg;
  80. if (sscanf(name, "fan%d", &n) == 1)
  81. st->parg.sn.type = SENSOR_FAN;
  82. else if (sscanf(name, "in%d", &n) == 1)
  83. st->parg.sn.type = SENSOR_IN;
  84. else if (sscanf(name, "temp%d", &n) == 1)
  85. st->parg.sn.type = SENSOR_TEMP;
  86. else
  87. fatal("sensor(%.200s): '%s' is a unknown sensor type; expected fan/in/temp",
  88. st->arg, name);
  89. /* Find the sensor in sysfs */
  90. p = &st->parg.sn.path[0];
  91. if (st->arg[0] == '/') {
  92. snprintf(p, MAX_PATH_LEN - 1, "%s_input", st->arg);
  93. p[MAX_PATH_LEN - 1] = '\0';
  94. if (stat(p, &pathinfo) < 0)
  95. fatal("sensor(%.200s): could not find sensor at '%.200s'",
  96. st->arg, p);
  97. } else {
  98. snprintf(p, MAX_PATH_LEN - 1, "/sys/class/hwmon/hwmon0/%s_input", st->arg);
  99. p[MAX_PATH_LEN - 1] = '\0';
  100. if (stat(p, &pathinfo) < 0) {
  101. snprintf(p, MAX_PATH_LEN - 1, "/sys/class/hwmon/hwmon0/device/%s_input", st->arg);
  102. p[MAX_PATH_LEN - 1] = '\0';
  103. if (stat(p, &pathinfo) < 0)
  104. fatal("sensor(%.200s): could not be found in /sys/class/hwmon/hwmon0[/device]/%s_input",
  105. st->arg, st->arg);
  106. }
  107. }
  108. get_sensor(buf, sizeof(buf), st);
  109. info("started module sensor(%.200s)", st->arg);
  110. }
  111. int
  112. get_sensor(char *symon_buf, int maxlen, struct stream *st)
  113. {
  114. FILE *f;
  115. double t;
  116. if ((f = fopen(st->parg.sn.path, "r")) == NULL)
  117. fatal("sensor(%s): cannot access %.200s: %.200s",
  118. st->arg, st->parg.sn.path, strerror(errno));
  119. if (fscanf(f, "%lf", &t) < 0) {
  120. warning("sensor(%s): cannot read sensor value",
  121. st->arg);
  122. return 0;
  123. }
  124. if (fclose(f) < 0)
  125. warning("sensor(%s): cannot close '%.200s'",
  126. st->arg, st->parg.sn.path);
  127. switch (st->parg.sn.type) {
  128. case SENSOR_TEMP:
  129. case SENSOR_IN:
  130. t /= 1000.0;
  131. break;
  132. }
  133. return snpack(symon_buf, maxlen, st->arg, MT_SENSOR, t);
  134. }