lmSensors.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:32k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. /* lmSensors.c
  2.  *
  3.  * Sections of this code were derived from the published API's of 
  4.  * some Sun products.  Hence, portions of the code may be copyright
  5.  * Sun Microsystems.
  6.  *
  7.  * This component allows net-snmp to report sensor information.
  8.  *
  9.  * In order to use it, the ./configure invocation must include...
  10.  *
  11.  * --with-mib-modules="ucd-snmp/lmSensors"
  12.  *
  13.  * It uses one of three different methodologies.  Some platforms make
  14.  * use of an lm_sensors driver to access the information on the
  15.  * health monitoring hardware, such as the LM75 and LM78 chips.
  16.  *
  17.  * For further information see http://secure.netroedge.com/~lm78/
  18.  *
  19.  * The Solaris platform uses the other two methodologies.  Earlier
  20.  * platforms such as the Enterprise 450 use kstat to report sensor
  21.  * information.  Later platforms, such as the V880 use the picld
  22.  * daemon to control system resources and report sensor information.
  23.  * Picld is supported only on Solaris 2.8 and later.
  24.  * 
  25.  * KSTAT
  26.  *
  27.  * The code initializes the kstat variables, then does a specific inquiry
  28.  * for what we're looking for.
  29.  *
  30.  * PICLD
  31.  *
  32.  * If picld is available on the platform, it tries to initialize picld.
  33.  * If that works, it points itself to the top of the picld btree
  34.  * and walks it way down recursively looking for sensors and child leafs.
  35.  * If it finds a child, it goes in and works it way down recursively.
  36.  * If it finds a sensor, it deals with it.
  37.  *
  38.  * Both these methodologies are implemented in a "read only" manner.
  39.  * You cannot use this code to change anything eg. fan speeds.
  40.  *
  41.  * The lmSensors component delivers the information documented in the
  42.  * LM-SENSORS-MIB.  The information is divided up as follows:
  43.  *
  44.  * -temperatures (Celsius)
  45.  * -fans (rpm's)
  46.  * -voltages
  47.  * -other (switches, LEDs and  i2c's (things that use the i2c bus))
  48.  * NOTE: This version does not support gpio's.  Still on the learning curve.
  49.  *
  50.  * Because the MIB only allows output of the datatype Gauge32 this
  51.  * limits the amount of meaningful information that can be delivered
  52.  * from "other" sensors.  Hence, the code does a certain amount of
  53.  * translating.  See the source for individual sensor types.
  54.  *
  55.  * If an "other" sensor delivers a value 99, it means that it
  56.  * is delivering a "status" that the code does not account for.
  57.  * If you discover one of these, please pass it on and I'll
  58.  * put it in.
  59.  *
  60.  * To see these messages, run the daemon as follows:
  61.  * 
  62.  * /usr/local/sbin/snmpd -f -L -Ducd-snmp/lmSensors
  63.  *
  64.  * or using gdb:
  65.  *
  66.  * gdb snmpd
  67.  * run -f -L -Ducd-snmp/lmSensors
  68.  *
  69.  * The component can record up to 256 instances of each type.
  70.  *
  71.  * The following should always be included first before anything else 
  72.  */
  73. #include <net-snmp/net-snmp-config.h>
  74. #include <net-snmp/net-snmp-includes.h>
  75. #include <net-snmp/agent/net-snmp-agent-includes.h>
  76. /*
  77.  * minimal include directives 
  78.  */
  79. #include "util_funcs.h"
  80. #include <time.h>
  81. /*
  82.  * Load required drivers and libraries.
  83.  */
  84. #ifdef solaris2
  85.     #include <kstat.h>
  86.     #ifdef HAVE_PICL_H 
  87.         #include <picl.h> /* accesses the picld daemon */
  88.     #endif 
  89.     #include </usr/platform/sun4u/include/sys/envctrl.h> /*should this be more generic? */
  90. #else
  91.     #include <sensors/sensors.h>
  92.     #define CONFIG_FILE_NAME "/etc/sensors.conf"
  93. #endif
  94. #include "lmSensors.h"
  95. #define N_TYPES      (4)
  96. #ifdef solaris2
  97.     #define MAX_NAME     (256)
  98.     #define MAX_SENSORS  (256) /* there's a lot of sensors on a v880 */
  99. #else
  100.     #define MAX_NAME     (64)
  101.     #define MAX_SENSORS  (128)
  102. #endif
  103. /*
  104.  * lmSensors_variables_oid:
  105.  *   this is the top level oid that we want to register under.  This
  106.  *   is essentially a prefix, with the suffix appearing in the
  107.  *   variable below.
  108.  */
  109. oid             lmSensors_variables_oid[] =
  110.     { 1, 3, 6, 1, 4, 1, 2021, 13, 16 };
  111. /*
  112.  * variable4 lmSensors_variables:
  113.  *   this variable defines function callbacks and type return information 
  114.  *   for the lmSensors mib section 
  115.  */
  116. struct variable4 lmSensors_variables[] = {
  117.     /*
  118.      * magic number        , variable type , ro/rw , callback fn  , L, oidsuffix 
  119.      */
  120. #define   LMTEMPSENSORSINDEX    3
  121.     {LMTEMPSENSORSINDEX, ASN_INTEGER, RONLY, var_lmSensorsTable, 3,
  122.      {2, 1, 1}},
  123. #define   LMTEMPSENSORSDEVICE   4
  124.     {LMTEMPSENSORSDEVICE, ASN_OCTET_STR, RONLY, var_lmSensorsTable, 3,
  125.      {2, 1, 2}},
  126. #define   LMTEMPSENSORSVALUE    5
  127.     {LMTEMPSENSORSVALUE, ASN_GAUGE, RONLY, var_lmSensorsTable, 3,
  128.      {2, 1, 3}},
  129. #define   LMFANSENSORSINDEX     8
  130.     {LMFANSENSORSINDEX, ASN_INTEGER, RONLY, var_lmSensorsTable, 3,
  131.      {3, 1, 1}},
  132. #define   LMFANSENSORSDEVICE    9
  133.     {LMFANSENSORSDEVICE, ASN_OCTET_STR, RONLY, var_lmSensorsTable, 3,
  134.      {3, 1, 2}},
  135. #define   LMFANSENSORSVALUE     10
  136.     {LMFANSENSORSVALUE, ASN_GAUGE, RONLY, var_lmSensorsTable, 3,
  137.      {3, 1, 3}},
  138. #define   LMVOLTSENSORSINDEX    13
  139.     {LMVOLTSENSORSINDEX, ASN_INTEGER, RONLY, var_lmSensorsTable, 3,
  140.      {4, 1, 1}},
  141. #define   LMVOLTSENSORSDEVICE   14
  142.     {LMVOLTSENSORSDEVICE, ASN_OCTET_STR, RONLY, var_lmSensorsTable, 3,
  143.      {4, 1, 2}},
  144. #define   LMVOLTSENSORSVALUE    15
  145.     {LMVOLTSENSORSVALUE, ASN_GAUGE, RONLY, var_lmSensorsTable, 3,
  146.      {4, 1, 3}},
  147. #define   LMMISCSENSORSINDEX    18
  148.     {LMMISCSENSORSINDEX, ASN_INTEGER, RONLY, var_lmSensorsTable, 3,
  149.      {5, 1, 1}},
  150. #define   LMMISCSENSORSDEVICE   19
  151.     {LMMISCSENSORSDEVICE, ASN_OCTET_STR, RONLY, var_lmSensorsTable, 3,
  152.      {5, 1, 2}},
  153. #define   LMMISCSENSORSVALUE    20
  154.     {LMMISCSENSORSVALUE, ASN_GAUGE, RONLY, var_lmSensorsTable, 3,
  155.      {5, 1, 3}},
  156. };
  157. typedef struct {
  158. #ifdef solaris2
  159.     #ifdef HAVE_PICL_H
  160.         char            name[PICL_PROPNAMELEN_MAX]; /*required for picld*/
  161.         int             value;
  162.     #else
  163.        char            name[MAX_NAME];
  164.        int             value;
  165.     #endif
  166. #else
  167.     char            name[MAX_NAME];
  168.     int             value;
  169. #endif
  170. } _sensor;
  171. typedef struct {
  172.     int             n;
  173.     _sensor         sensor[MAX_SENSORS];
  174. } _sensor_array;
  175. static _sensor_array sensor_array[N_TYPES];
  176. static clock_t  timestamp;
  177. static int      sensor_init(void);
  178. static void     sensor_load(void);
  179. static void     _sensor_load(clock_t t);
  180. /*
  181.  * init_lmSensors():
  182.  *   Initialization routine.  This is called when the agent starts up.
  183.  *   At a minimum, registration of your variables should take place here.
  184.  */
  185. void
  186. init_lmSensors(void)
  187. {
  188.    sensor_init(); 
  189.     /*
  190.      * register ourselves with the agent to handle our mib tree 
  191.      */
  192.     REGISTER_MIB("lmSensors", lmSensors_variables, variable4,
  193.                  lmSensors_variables_oid);
  194. }
  195. /*
  196.  * var_lmSensorsTable():
  197.  *   Handle this table separately from the scalar value case.
  198.  *   The workings of this are basically the same as for var_lmSensors above.
  199.  */
  200. unsigned char  *
  201. var_lmSensorsTable(struct variable *vp,
  202.                    oid * name,
  203.                    size_t * length,
  204.                    int exact,
  205.                    size_t * var_len, WriteMethod ** write_method)
  206. {
  207.     static long     long_ret;
  208.     static unsigned char string[SPRINT_MAX_LEN];
  209.     int             s_index;
  210.     int             s_type = -1;
  211.     int             n_sensors;
  212.     _sensor         s;
  213.     sensor_load();
  214.     switch (vp->magic) {
  215.     case LMTEMPSENSORSINDEX:
  216.     case LMTEMPSENSORSDEVICE:
  217.     case LMTEMPSENSORSVALUE:
  218.         s_type = 0;
  219.         n_sensors = sensor_array[0].n;
  220.         break;
  221.     case LMFANSENSORSINDEX:
  222.     case LMFANSENSORSDEVICE:
  223.     case LMFANSENSORSVALUE:
  224.         s_type = 1;
  225.         n_sensors = sensor_array[1].n;
  226.         break;
  227.     case LMVOLTSENSORSINDEX:
  228.     case LMVOLTSENSORSDEVICE:
  229.     case LMVOLTSENSORSVALUE:
  230.         s_type = 2;
  231.         n_sensors = sensor_array[2].n;
  232.         break;
  233.     case LMMISCSENSORSINDEX:
  234.     case LMMISCSENSORSDEVICE:
  235.     case LMMISCSENSORSVALUE:
  236.         s_type = 3;
  237.         n_sensors = sensor_array[3].n;
  238.         break;
  239.     default:
  240.         s_type = -1;
  241.         n_sensors = 0;
  242.     }
  243.     if (header_simple_table(vp, name, length, exact,
  244.                             var_len, write_method,
  245.                             n_sensors) == MATCH_FAILED)
  246.         return NULL;
  247.     if (s_type < 0)
  248.         return NULL;
  249.     s_index = name[*length - 1] - 1;
  250.     s = sensor_array[s_type].sensor[s_index];
  251.     switch (vp->magic) {
  252.     case LMTEMPSENSORSINDEX:
  253.     case LMFANSENSORSINDEX:
  254.     case LMVOLTSENSORSINDEX:
  255.     case LMMISCSENSORSINDEX:
  256.         long_ret = s_index;
  257.         return (unsigned char *) &long_ret;
  258.     case LMTEMPSENSORSDEVICE:
  259.     case LMFANSENSORSDEVICE:
  260.     case LMVOLTSENSORSDEVICE:
  261.     case LMMISCSENSORSDEVICE:
  262.         strncpy(string, s.name, SPRINT_MAX_LEN - 1);
  263.         *var_len = strlen(string);
  264.         return (unsigned char *) string;
  265.     case LMTEMPSENSORSVALUE:
  266.     case LMFANSENSORSVALUE:
  267.     case LMVOLTSENSORSVALUE:
  268.     case LMMISCSENSORSVALUE:
  269.         long_ret = s.value;
  270.         return (unsigned char *) &long_ret;
  271.     default:
  272.         ERROR_MSG("Unable to handle table request");
  273.     }
  274.     return NULL;
  275. }
  276. static int
  277. sensor_init(void)
  278. {
  279. #ifndef solaris2
  280.     int             res;
  281.     char            filename[] = CONFIG_FILE_NAME;
  282.     clock_t         t = clock();
  283.     FILE           *fp = fopen(filename, "r");
  284.     if (!fp)
  285.         return 1;
  286.     if ((res = sensors_init(fp)))
  287.         return 2;
  288.     _sensor_load(t); /* I'll let the linux people decide whether they want to load right away */
  289. #endif
  290.     return 0;
  291. }
  292. static void
  293. sensor_load(void)
  294. {
  295. #ifdef solaris2
  296.     clock_t         t = time(NULL);
  297. #else
  298.     clock_t t = clock();
  299. #endif
  300.     if (t > timestamp + 6) /* this may require some tuning - currently 6 seconds*/
  301.         _sensor_load(t);
  302.     return;
  303. }
  304. /* This next code block includes all kstat and picld code for the Solaris platform.
  305.  * If you're not compiling on a Solaris that supports picld, it won't be included.
  306.  */
  307. #ifdef solaris2
  308. /* *******  picld sensor procedures * */
  309. #ifdef HAVE_PICL_H
  310. static void
  311. process_individual_fan(picl_nodehdl_t childh, 
  312.                      char propname[PICL_PROPNAMELEN_MAX])
  313. {
  314.     picl_nodehdl_t  sensorh;
  315.     picl_propinfo_t sensor_info;
  316.     int speed;
  317.     int typ = 1; /*fan*/
  318.     picl_errno_t    error_code,ec2;
  319.     if (sensor_array[typ].n >= MAX_SENSORS){
  320.         snmp_log(LOG_ERR, "There are too many sensors of type %dn",typ);
  321.         }
  322.     else{
  323.         error_code = (picl_get_propinfo_by_name(childh,
  324.                          "AtoDSensorValue",&sensor_info,&sensorh));
  325.         if (error_code == PICL_SUCCESS) {
  326.              ec2 = picl_get_propval(sensorh,&speed,sizeof(speed));
  327.              if (ec2 == PICL_SUCCESS){
  328.                  sensor_array[typ].sensor[sensor_array[typ].n].value = speed;
  329.                  snprintf(sensor_array[typ].sensor[sensor_array[typ].n].name,
  330.                      (PICL_PROPNAMELEN_MAX - 1),"%s",propname);
  331.                  sensor_array[typ].sensor[sensor_array[typ].n].
  332.                      name[PICL_PROPNAMELEN_MAX - 1] = '';
  333.                  sensor_array[typ].n++;
  334.                  } /*end if ec2*/
  335.              else
  336.                  DEBUGMSGTL(("ucd-snmp/lmSensors", 
  337.                      "sensor value read error code->%dn",ec2));
  338.             } /* end if */
  339.         else
  340.             DEBUGMSGTL(("ucd-snmp/lmSensors", 
  341.                 "sensor lookup failed  error code->%dn",error_code));
  342.         }
  343. } /*process individual fan*/
  344. static void
  345. process_temperature_sensor(picl_nodehdl_t childh,
  346.                                char propname[PICL_PROPNAMELEN_MAX])
  347. {
  348.     picl_nodehdl_t  sensorh;
  349.     picl_propinfo_t sensor_info;
  350.     int temp;
  351.     int typ = 0; /*temperature*/
  352.     picl_errno_t    error_code,ec2;
  353.     if (sensor_array[typ].n >= MAX_SENSORS){
  354.         snmp_log(LOG_ERR, "There are too many sensors of type %dn",typ);
  355.         }
  356.     else{
  357.         error_code = (picl_get_propinfo_by_name(childh,
  358.                          "Temperature",&sensor_info,&sensorh));
  359.         if (error_code == PICL_SUCCESS) {
  360.              ec2 = picl_get_propval(sensorh,&temp,sizeof(temp));
  361.              if (ec2 == PICL_SUCCESS){
  362.                  sensor_array[typ].sensor[sensor_array[typ].n].value = temp;
  363.                  snprintf(sensor_array[typ].sensor[sensor_array[typ].n].name,
  364.                      (PICL_PROPNAMELEN_MAX - 1),"%s",propname);
  365.                  sensor_array[typ].sensor[sensor_array[typ].n].
  366.                      name[PICL_PROPNAMELEN_MAX - 1] = '';
  367.                  sensor_array[typ].n++;
  368.                  } /*end if ec2*/
  369.              else
  370.                  DEBUGMSGTL(("ucd-snmp/lmSensors", 
  371.                                "sensor value read error code->%dn",ec2));
  372.             } /* end if */
  373.         else
  374.             DEBUGMSGTL(("ucd-snmp/lmSensors", 
  375.                 "sensor lookup failed  error code->%dn",error_code));
  376.         }
  377. }  /* process temperature sensor */
  378. static void
  379. process_digital_sensor(picl_nodehdl_t childh,
  380.                    char propname[PICL_PROPNAMELEN_MAX])
  381. {
  382.     picl_nodehdl_t  sensorh;
  383.     picl_propinfo_t sensor_info;
  384.     int temp; /*volts?*/
  385.     int typ = 2; /*volts*/
  386.     picl_errno_t    error_code,ec2;
  387.     if (sensor_array[typ].n >= MAX_SENSORS){
  388.         snmp_log(LOG_ERR, "There are too many sensors of type %dn",typ);
  389.         }
  390.     else{
  391.         error_code = (picl_get_propinfo_by_name(childh,
  392.                           "AtoDSensorValue",&sensor_info,&sensorh));
  393.         if (error_code == PICL_SUCCESS) {
  394.              ec2 = picl_get_propval(sensorh,&temp,sizeof(temp));
  395.              if (ec2 == PICL_SUCCESS){
  396.                  sensor_array[typ].sensor[sensor_array[typ].n].value = temp;
  397.                  snprintf(sensor_array[typ].sensor[sensor_array[typ].n].name,
  398.                     (PICL_PROPNAMELEN_MAX - 1),"%s",propname);
  399.                  sensor_array[typ].sensor[sensor_array[typ].n].
  400.                       name[PICL_PROPNAMELEN_MAX - 1] = '';
  401.                  sensor_array[typ].n++;
  402.                  }
  403.              else
  404.                  DEBUGMSGTL(("ucd-snmp/lmSensors", 
  405.                    "sensor value read error code->%dn",ec2));
  406.             } /* end if */
  407.         else
  408.             DEBUGMSGTL(("ucd-snmp/lmSensors", 
  409.               "sensor lookup failed  error code->%dn",error_code));
  410.         }
  411. }  /* process digital sensor */
  412. static void
  413. process_switch(picl_nodehdl_t childh,
  414.                    char propname[PICL_PROPNAMELEN_MAX])
  415. {
  416.     picl_nodehdl_t  sensorh;
  417.     picl_propinfo_t sensor_info;
  418.     char state[32];
  419.     int st_cnt;
  420.     const char *switch_settings[]={"OFF","ON","NORMAL","LOCKED","UNKNOWN",
  421.                                     "DIAG","SECURE"};
  422.     u_int value;
  423.     u_int found = 0;
  424.     int max_key_posns = 7;
  425.     int typ = 3; /*other*/
  426.     if (sensor_array[typ].n >= MAX_SENSORS){
  427.         snmp_log(LOG_ERR, "There are too many sensors of type %dn",typ);
  428.         }
  429.     else{
  430.         picl_errno_t    error_code,ec2;
  431.         error_code = (picl_get_propinfo_by_name(childh,
  432.                          "State",&sensor_info,&sensorh));
  433.         if (error_code == PICL_SUCCESS) {
  434.              ec2 = picl_get_propval(sensorh,&state,sensor_info.size);
  435.              if (ec2 == PICL_SUCCESS){
  436.                  for (st_cnt=0;st_cnt < max_key_posns;st_cnt++){
  437.                      if (strncmp(state,switch_settings[st_cnt],
  438.                            strlen(switch_settings[st_cnt])) == 0){
  439.                          value = st_cnt;
  440.                          found = 1;
  441.                          break;
  442.                          } /* end if */
  443.                      } /* end for */
  444.                  if (found==0)
  445.                      value = 99;
  446.                  sensor_array[typ].sensor[sensor_array[typ].n].value = value;
  447.                  snprintf(sensor_array[typ].sensor[sensor_array[typ].n].name,
  448.                      (PICL_PROPNAMELEN_MAX - 1),"%s",propname);
  449.                  sensor_array[typ].sensor[sensor_array[typ].n].
  450.                      name[PICL_PROPNAMELEN_MAX - 1] = '';
  451.                  sensor_array[typ].n++;
  452.                  } /*end if ec2*/
  453.              else
  454.                  DEBUGMSGTL(("ucd-snmp/lmSensors",
  455.                      "sensor value read error code->%dn",ec2));
  456.             } /* end if */
  457.         else
  458.             DEBUGMSGTL(("ucd-snmp/lmSensors",
  459.                 "sensor lookup failed  error code->%dn",error_code));
  460.         }
  461. } /*process switch*/
  462. static void
  463. process_led(picl_nodehdl_t childh,
  464.                    char propname[PICL_PROPNAMELEN_MAX])
  465. {
  466.     picl_nodehdl_t  sensorh;
  467.     picl_propinfo_t sensor_info;
  468.     char state[32];
  469.     int st_cnt;
  470.     const char *led_settings[]={"OFF","ON","BLINK"};
  471.     u_int value;
  472.     u_int found = 0;
  473.     int max_led_posns = 3;
  474.     int typ = 3; 
  475.     picl_errno_t    error_code,ec2;
  476.     if (sensor_array[typ].n >= MAX_SENSORS){
  477.         snmp_log(LOG_ERR, "There are too many sensors of type %dn",typ);
  478.         }
  479.     else{
  480.         error_code = (picl_get_propinfo_by_name(childh,
  481.                          "State",&sensor_info,&sensorh));
  482.         if (error_code == PICL_SUCCESS) {
  483.              ec2 = picl_get_propval(sensorh,&state,sensor_info.size);
  484.              if (ec2 == PICL_SUCCESS){
  485.                  for (st_cnt=0; st_cnt < max_led_posns; st_cnt++){
  486.                      if (strncmp(state,led_settings[st_cnt],
  487.                            strlen(led_settings[st_cnt])) == 0){
  488.                          value=st_cnt;
  489.                          found = 1;
  490.                          break;
  491.                          } 
  492.                      } 
  493.                  if (found==0)
  494.                      value = 99;
  495.                  sensor_array[typ].sensor[sensor_array[typ].n].value = value;
  496.                  snprintf(sensor_array[typ].sensor[sensor_array[typ].n].name,
  497.                      (PICL_PROPNAMELEN_MAX - 1),"%s",propname);
  498.                  sensor_array[typ].sensor[sensor_array[typ].n].
  499.                      name[PICL_PROPNAMELEN_MAX - 1] = '';
  500.                  sensor_array[typ].n++;
  501.                  }
  502.              else
  503.                  DEBUGMSGTL(("ucd-snmp/lmSensors",
  504.                      "sensor value read error code->%dn",ec2));
  505.             } 
  506.         else
  507.             DEBUGMSGTL(("ucd-snmp/lmSensors",
  508.                 "sensor lookup failed  error code->%dn",error_code));
  509.        }
  510. static void
  511. process_i2c(picl_nodehdl_t childh,
  512.                    char propname[PICL_PROPNAMELEN_MAX])
  513. {
  514.     picl_nodehdl_t  sensorh;
  515.     picl_propinfo_t sensor_info;
  516.     char state[32];
  517.     int st_cnt;
  518.     const char *i2c_settings[]={"OK"};
  519.     u_int value;
  520.     u_int found = 0;
  521.     int max_i2c_posns = 1;
  522.     int typ = 3; 
  523.     picl_errno_t    error_code,ec2;
  524.     if (sensor_array[typ].n >= MAX_SENSORS){
  525.         snmp_log(LOG_ERR, "There are too many sensors of type %dn",typ);
  526.         }
  527.     else{
  528.         error_code = (picl_get_propinfo_by_name(childh,
  529.                          "State",&sensor_info,&sensorh));
  530.         if (error_code == PICL_SUCCESS) {
  531.              DEBUGMSGTL(("ucd-snmp/lmSensors","Found i2c record size %dn",sensor_info.size));
  532.              ec2 = picl_get_propval(sensorh,&state,sensor_info.size);
  533.              if (ec2 == PICL_SUCCESS){
  534.                  for (st_cnt=0;st_cnt < max_i2c_posns;st_cnt++){
  535.                      if (strncmp(state,i2c_settings[st_cnt],
  536.                            strlen(i2c_settings[st_cnt])) == 0){
  537.                          value=st_cnt;
  538.                          found = 1;
  539.                          break;
  540.                          } 
  541.                      } 
  542.                  if (found==0)
  543.                      value = 99;
  544.                  sensor_array[typ].sensor[sensor_array[typ].n].value = value;
  545.                  snprintf(sensor_array[typ].sensor[sensor_array[typ].n].name,
  546.                      (PICL_PROPNAMELEN_MAX - 1),"%s",propname);
  547.                  sensor_array[typ].sensor[sensor_array[typ].n].
  548.                      name[PICL_PROPNAMELEN_MAX - 1] = '';
  549.                  sensor_array[typ].n++;
  550.                  } 
  551.              else
  552.                  DEBUGMSGTL(("ucd-snmp/lmSensors",
  553.                      "sensor value read error code->%dn",ec2));
  554.             }
  555.         else
  556.             DEBUGMSGTL(("ucd-snmp/lmSensors",
  557.                 "sensor lookup failed  error code->%dn",error_code));
  558.         }
  559. }
  560. static int
  561. process_sensors(int level, picl_nodehdl_t nodeh)
  562. {
  563.     picl_nodehdl_t  childh;
  564.     char propname[PICL_PROPNAMELEN_MAX];
  565.     char propclass[PICL_CLASSNAMELEN_MAX];
  566.     picl_errno_t error_code;
  567.     picl_prophdl_t prop_handle;
  568.     picl_propinfo_t prop_info;
  569.     level++;
  570. /*
  571.     DEBUGMSGTL(("ucd-snmp/lmSensors","Processing sensors level %dn",level));
  572. */
  573.     error_code = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, propclass,
  574.                                         (PICL_PROPNAMELEN_MAX-1));
  575.     if (error_code != PICL_SUCCESS) {
  576.         DEBUGMSG(("ucd-snmp/lmSensors","Couldn't get propclassn"));
  577.                 return (error_code);
  578.     }
  579.     error_code = picl_get_prop_by_name(nodeh, PICL_PROP_NAME, &prop_handle);
  580.     if (error_code != PICL_SUCCESS) {
  581.         DEBUGMSGTL(("ucd-snmp/lmSensors","Couldn't get prop_handlen"));
  582.         return (error_code);
  583.     }
  584.     error_code = picl_get_propinfo(prop_handle, &prop_info);
  585.     if (error_code != PICL_SUCCESS) {
  586.         DEBUGMSGTL(("ucd-snmp/lmSensors","Couldn't get prop informationn"));
  587.         return (error_code);
  588.     }
  589.     error_code=picl_get_propval(prop_handle, propname, (PICL_PROPNAMELEN_MAX-1));
  590.     DEBUGMSGTL(("ucd-snmp/lmSensors","found propname %s of class %sn",propname, propclass));
  591.     if (error_code != PICL_SUCCESS) {
  592.         DEBUGMSGTL(("ucd-snmp/lmSensors","Couldn't get prop handle by namen"));
  593.         return (error_code);
  594.     }
  595.     if (strstr(propclass,"flashprom"))
  596.        DEBUGMSGTL(("ucd-snmp/lmSensors","found a flashpromn"));
  597.     if (strstr(propclass,"fan-tachometer"))
  598.         process_individual_fan(nodeh,propname);
  599.     if (strstr(propclass,"temperature-sensor"))
  600.         process_temperature_sensor(nodeh,propname);
  601.     if (strstr(propclass,"digital-sensor"))
  602.         process_digital_sensor(nodeh,propname);
  603.     if (strstr(propclass,"switch"))
  604.         process_switch(nodeh,propname);
  605.     if (strstr(propclass,"led"))
  606.         process_led(nodeh,propname);
  607.     if (strstr(propclass,"i2c"))
  608.         process_i2c(nodeh,propname);
  609. /*
  610.         if (strstr(propclass,"gpio"))
  611.             process_gpio(prop_handle,propname); 
  612. */
  613.     for (error_code = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD,
  614.           &childh, sizeof (picl_nodehdl_t)); 
  615.           error_code != PICL_PROPNOTFOUND;
  616.           error_code = picl_get_propval_by_name(childh, PICL_PROP_PEER,
  617.            &childh, sizeof (picl_nodehdl_t))) {
  618.        if (error_code != PICL_SUCCESS) {
  619.             return (error_code);
  620.           }
  621.        /* call itself recursively */
  622.        error_code = process_sensors(level,childh);
  623.        if (error_code != PICL_SUCCESS)
  624.            return (error_code);
  625.        } /* end for */
  626.     return (PICL_SUCCESS);
  627. } /* process sensors */
  628. #endif
  629. /* ******** end of picld sensor procedures * */
  630. #endif /* solaris2 */
  631. static void
  632. _sensor_load(clock_t t)
  633. {
  634. #ifdef solaris2
  635.     int i,j;
  636.     int typ;
  637.     int temp;
  638.     int other;
  639.     const char *fantypes[]={"CPU","PWR","AFB"};
  640.     kstat_ctl_t *kc;
  641.     kstat_t *kp;
  642.     envctrl_fan_t *fan_info;
  643.     envctrl_ps_t *power_info;
  644.     envctrl_encl_t *enc_info;
  645. #ifdef HAVE_PICL_H
  646.     int er_code;
  647.     picl_errno_t     error_code;
  648.     int level=0;
  649.     picl_nodehdl_t  rooth;
  650. #endif 
  651.  DEBUGMSGTL(("ucd-snmp/lmSensors", "Reading the sensorsn")); 
  652. /* initialize the array */
  653.     for (i = 0; i < N_TYPES; i++){
  654.         sensor_array[i].n = 0;
  655.         for (j=0; j < MAX_SENSORS; j++){
  656.             sensor_array[i].sensor[j].name[0] = '';
  657.             sensor_array[i].sensor[j].value = 0;
  658.              }
  659.         } /*end for i*/
  660. /* try picld (if supported), then try kstat */
  661. #ifdef HAVE_PICL_H 
  662. DEBUGMSGTL(("ucd-snmp/lmSensors","trying picld firstn"));
  663. er_code = picl_initialize();
  664. if (er_code == PICL_SUCCESS) {
  665.     DEBUGMSGTL(("ucd-snmp/lmSensors","Got into picldn"));
  666.     error_code = picl_get_root(&rooth);
  667.     if (error_code != PICL_SUCCESS) {
  668.         DEBUGMSGTL(("ucd-snmp/lmSensors", "picld couldn't get root error code->%dn",error_code));
  669.         }
  670.     else{
  671.         DEBUGMSGTL(("ucd-snmp/lmSensors", "found rootn"));
  672.         error_code = process_sensors(level, rooth);
  673.        } /* end else */
  674.     picl_shutdown();
  675. }  /* end if err_code for picl_initialize */
  676. else {
  677.     DEBUGMSGTL(("ucd-snmp/lmSensors","No picld availablen"));
  678. } /*end else picl_initialize */
  679. #endif  /* end of picld section */
  680. /* initialize kstat */
  681. kc = kstat_open();
  682. if (kc == 0) {
  683.     DEBUGMSGTL(("ucd-snmp/lmSensors", "couldn't open kstatn"));
  684.     } /* endif kc */
  685. else{
  686.     DEBUGMSGTL(("ucd-snmp/lmSensors", "Opened kstat - looking for sensorsn"));
  687.     kp = kstat_lookup(kc, ENVCTRL_MODULE_NAME, 0, ENVCTRL_KSTAT_FANSTAT);
  688.     if (kp == 0) {
  689.         DEBUGMSGTL(("ucd-snmp/lmSensors", "couldn't lookup fan kstatn"));
  690.         } /* endif lookup fans */
  691.     else{
  692.         if (kstat_read(kc, kp, 0) == -1) {
  693.             DEBUGMSGTL(("ucd-snmp/lmSensors", "couldn't read fan kstatn"));
  694.             } /* endif kstatread fan */
  695.         else{
  696.             typ = 1;
  697.             fan_info = (envctrl_fan_t *) kp->ks_data;
  698.             sensor_array[typ].n = kp->ks_ndata;
  699.             for (i=0; i < kp->ks_ndata; i++){
  700.                 DEBUGMSGTL(("ucd-snmp/lmSensors", "found instance %d fan type %d speed %d OK %d bustedfan %dn",
  701.                     fan_info->instance, fan_info->type,fan_info->fanspeed,fan_info->fans_ok,fan_info->fanflt_num));
  702.                 sensor_array[typ].sensor[i].value = fan_info->fanspeed;
  703.                 snprintf(sensor_array[typ].sensor[i].name,(MAX_NAME - 1),
  704.                    "fan type %s number %d",fantypes[fan_info->type],fan_info->instance);
  705.                 sensor_array[typ].sensor[i].name[MAX_NAME - 1] = '';
  706.                 fan_info++;
  707.                 } /* end for fan_info */
  708.             } /* end else kstatread fan */
  709.         } /* end else lookup fans*/
  710.     kp = kstat_lookup(kc, ENVCTRL_MODULE_NAME, 0, ENVCTRL_KSTAT_PSNAME);
  711.     if (kp == 0) {
  712.         DEBUGMSGTL(("ucd-snmp/lmSensors", "couldn't lookup power supply kstatn"));
  713.         } /* endif lookup power supply */
  714.     else{
  715.         if (kstat_read(kc, kp, 0) == -1) {
  716.             DEBUGMSGTL(("ucd-snmp/lmSensors", "couldn't read power supply kstatn"));
  717.             } /* endif kstatread fan */
  718.         else{
  719.             typ = 2;
  720.             power_info = (envctrl_ps_t *) kp->ks_data;
  721.             sensor_array[typ].n = kp->ks_ndata;
  722.             for (i=0; i < kp->ks_ndata; i++){
  723.                 DEBUGMSGTL(("ucd-snmp/lmSensors", "found instance %d psupply temp %d %dW OK %d share %d limit %dn",
  724.                     power_info->instance, power_info->ps_tempr,power_info->ps_rating,
  725.                     power_info->ps_ok,power_info->curr_share_ok,power_info->limit_ok));
  726.                 sensor_array[typ].sensor[i].value = power_info->ps_tempr;
  727.                 snprintf(sensor_array[typ].sensor[i].name,(MAX_NAME-1),
  728.                          "power supply %d",power_info->instance);
  729.                 sensor_array[typ].sensor[i].name[MAX_NAME - 1] = '';
  730.                 power_info++;
  731.                 } /* end for power_info */
  732.             } /* end else kstatread power supply */
  733.         } /* end else lookup power supplies*/
  734.     kp = kstat_lookup(kc, ENVCTRL_MODULE_NAME, 0, ENVCTRL_KSTAT_ENCL);
  735.     if (kp == 0) {
  736.         DEBUGMSGTL(("ucd-snmp/lmSensors", "couldn't lookup enclosure kstatn"));
  737.         } /* endif lookup enclosure */
  738.     else{
  739.         if (kstat_read(kc, kp, 0) == -1) {
  740.             DEBUGMSGTL(("ucd-snmp/lmSensors", "couldn't read enclosure kstatn"));
  741.             } /* endif kstatread enclosure */
  742.         else{
  743.             enc_info = (envctrl_encl_t *) kp->ks_data; 
  744.             temp = 0;
  745.             other = 0;
  746.             for (i=0; i < kp->ks_ndata; i++){
  747.                switch (enc_info->type){
  748.                case ENVCTRL_ENCL_FSP:
  749.                    DEBUGMSGTL(("ucd-snmp/lmSensors", "front panel value %dn",enc_info->value));
  750.                    typ = 3; /* misc */
  751.                    sensor_array[typ].sensor[other].value = enc_info->value;
  752.                    strncpy(sensor_array[typ].sensor[other].name,"FSP",MAX_NAME-1);
  753.                    sensor_array[typ].sensor[other].name[MAX_NAME-1]=''; /* null terminate */
  754.                    other++;
  755.                    break;
  756.                case ENVCTRL_ENCL_AMBTEMPR:
  757.                    DEBUGMSGTL(("ucd-snmp/lmSensors", "ambient temp %dn",enc_info->value));
  758.                    typ = 0; /* temperature sensor */
  759.                    sensor_array[typ].sensor[temp].value = enc_info->value;
  760.                    strncpy(sensor_array[typ].sensor[temp].name,"Ambient",MAX_NAME-1);
  761.                    sensor_array[typ].sensor[temp].name[MAX_NAME-1]=''; /* null terminate */
  762.                    temp++;
  763.                    break;
  764.                case ENVCTRL_ENCL_BACKPLANE4:
  765.                    DEBUGMSGTL(("ucd-snmp/lmSensors", "There is a backplane4n"));
  766.                    typ = 3; /* misc */
  767.                    sensor_array[typ].sensor[other].value = enc_info->value;
  768.                    strncpy(sensor_array[typ].sensor[other].name,"Backplane4",MAX_NAME-1);
  769.                    sensor_array[typ].sensor[other].name[MAX_NAME-1]=''; /* null terminate */
  770.                    other++;
  771.                    break;
  772.                case ENVCTRL_ENCL_BACKPLANE8:
  773.                    DEBUGMSGTL(("ucd-snmp/lmSensors", "There is a backplane8n"));
  774.                    typ = 3; /* misc */
  775.                    sensor_array[typ].sensor[other].value = enc_info->value;
  776.                    strncpy(sensor_array[typ].sensor[other].name,"Backplane8",MAX_NAME-1);
  777.                    sensor_array[typ].sensor[other].name[MAX_NAME-1]=''; /* null terminate */
  778.                    other++;
  779.                    break;
  780.                case ENVCTRL_ENCL_CPUTEMPR:
  781.                    DEBUGMSGTL(("ucd-snmp/lmSensors", "CPU%d temperature %dn",enc_info->instance,enc_info->value));
  782.                    typ = 0; /* temperature sensor */
  783.                    sensor_array[typ].sensor[temp].value = enc_info->value;
  784.                    snprintf(sensor_array[typ].sensor[temp].name,MAX_NAME,"CPU%d",enc_info->instance);
  785.                    sensor_array[typ].sensor[other].name[MAX_NAME-1]=''; /* null terminate */
  786.                    temp++;
  787.                    break;
  788.                default:
  789.                    DEBUGMSGTL(("ucd-snmp/lmSensors", "unknown element instance &d type &d value %dn",
  790.                        enc_info->instance, enc_info->type, enc_info->value));
  791.                    break;
  792.                } /* end switch */
  793.                enc_info++;
  794.                } /* end for enc_info */
  795.                sensor_array[3].n = other;
  796.                sensor_array[0].n = temp;
  797.             } /* end else kstatread enclosure */
  798.         } /* end else lookup enclosure*/
  799.     kstat_close(kc);
  800. } /* end else kstat */
  801. #else /* end solaris2 */
  802.     const sensors_chip_name *chip;
  803.     const sensors_feature_data *data;
  804.     int             chip_nr = 0;
  805.     int             i;
  806.     for (i = 0; i < N_TYPES; i++)
  807.         sensor_array[i].n = 0;
  808.     while ((chip = sensors_get_detected_chips(&chip_nr))) {
  809. int             a = 0;
  810. int             b = 0;
  811.         while ((data = sensors_get_all_features(*chip, &a, &b))) {
  812.             char           *label = NULL;
  813.             double          val;
  814.             if ((data->mode & SENSORS_MODE_R) &&
  815.                 (data->mapping == SENSORS_NO_MAPPING) &&
  816.                 !sensors_get_label(*chip, data->number, &label) &&
  817.                 !sensors_get_feature(*chip, data->number, &val)) {
  818.                 int             type = -1;
  819.                 float           mul;
  820.                 _sensor_array  *array;
  821.                 if (strstr(label, "V")) {
  822.                     type = 2;
  823.                     mul = 1000.0;
  824.                 }
  825.                 if (strstr(label, "fan") || strstr(label, "Fan")) {
  826.                     type = 1;
  827.                     mul = 1.0;
  828.                 }
  829.                 if (strstr(label, "temp") || strstr(label, "Temp")) {
  830.                     type = 0;
  831.                     mul = 1000.0;
  832.                 }
  833.                 if (type == -1) {
  834.                     type = 3;
  835.                     mul = 1000.0;
  836.                 }
  837.                 array = &sensor_array[type];
  838.                 if (MAX_SENSORS <= array->n) {
  839.                     snmp_log(LOG_ERR, "too many sensors. ignoring %sn", label);
  840.                     break;
  841.                 }
  842.                 strncpy(array->sensor[array->n].name, label, MAX_NAME);
  843.                 array->sensor[array->n].value = (int) (val * mul);
  844.                 DEBUGMSGTL(("ucd-snmp/lmSensors","sensor %d, value %dn",
  845.                             array->sensor[array->n].name,
  846.                             array->sensor[array->n].value));
  847.                 array->n++;
  848.             }
  849.     if (label) {
  850. free(label);
  851. label = NULL;
  852.     }
  853.         }
  854.     }
  855. #endif /*else solaris2 */
  856.     timestamp = t;
  857. }