Mike Fisher wrote:
Bruce Shaw wrote:
Could you post it as a patch? I'd like to have a look at it. My code works on my E450's, V880's and 280r's.


Minor clarification: I have code, but it's not been integrated back into the agent yet. (hence my original query) It's also not working as well as I first thought. It find finds the sensors nicely, but getting the correct values out of some of the platforms is not as straight forward as others. The V210 and V440 are giving me problems at the moment. I'll try to clean it up a bit and post what I have sometime tomorrow.

Here it is, as promised. It should correctly report any fan tachs, temperature and voltage sensors, digital sensors, switches, LEDs, and i2c devices. I've run it successfully on a SunBlade 100, 280R, V210, V440, V480, V490, V4800, V880, V1280, and E2900. I'd be interested in seeing results from a V240, V4900, V890, and any other picl-equipped platforms I missed.

Mike


/*  picltest.c  - Sun picl test code based on net-snmp's lmSensors.c
                  To build: gcc -o picltest -lpicl picltest.c
                  Mike Fisher - 6/9/2005
*/

#include <stdio.h>
#include <errno.h>
#include <unistd.h>

#include <picl.h>

#define DEBUGMSG(x) //printf x

static void _sensor_load();
static int process_sensors();
static int process_individual_fan();
static int process_digital_sensor();
static int process_switch();
static int process_led();
static int process_i2c();
static int process_voltage_sensor();
static int process_temperature_sensor();
static void debug();
static int read_num_sensor();
static int read_enum_sensor();


main()
{
  _sensor_load();
}

//#############################################################################

static void
_sensor_load() {
  int i,j;	
  int typ;	
  int temp;	
  int other;	
  int er_code;	
  
  picl_errno_t     error_code;
  picl_nodehdl_t  rooth,plath;
  

  /* try picld (if supported), if that doesn't work, try kstat */

  er_code = picl_initialize();
  
  if (er_code == PICL_SUCCESS) {
    error_code = picl_get_root(&rooth);
    
    if (error_code != PICL_SUCCESS) {
      DEBUGMSG(("picld couldn't get root error code->%d\n",error_code));
    } else {
      error_code = process_sensors(rooth);

      if (error_code != PICL_PROPNOTFOUND)
	DEBUGMSG(("picld had an internal problem error code->%d\n",
		  error_code));
    }
    
    picl_shutdown();
  } 
}

//#############################################################################

static int
process_sensors(picl_nodehdl_t nodeh)
{
  picl_nodehdl_t  childh;
  picl_nodehdl_t  nexth;

  char            propname[PICL_PROPNAMELEN_MAX];
  char            propclass[PICL_CLASSNAMELEN_MAX];
  picl_errno_t    error_code;

  /* look up first child node */
  error_code = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD, &childh,
                                        sizeof (picl_nodehdl_t));
  if (error_code != PICL_SUCCESS) {
    DEBUGMSG(("picl_get_propval_by_name(%s) %d\n",
	      PICL_PROP_CHILD, error_code));
    return (error_code);
  }
  
  /* step through child nodes, get the name first */
  while (error_code == PICL_SUCCESS) {
    
    error_code = picl_get_propval_by_name(childh, PICL_PROP_NAME,
					  propname, (PICL_PROPNAMELEN_MAX - 1));
    if (error_code != PICL_SUCCESS) {  /* a node with no name.  Impossible! */
      DEBUGMSG(("picl_get_propval_by_name(%s) = %d\n",
		PICL_PROP_NAME, error_code));
      return (error_code);
    }
    
    error_code = picl_get_propval_by_name(childh, PICL_PROP_CLASSNAME,
					  propclass, sizeof (propclass));
    if (error_code != PICL_SUCCESS) {  /* a node with no class?  Impossible! */
      DEBUGMSG(("picl_get_propval_by_name(%s) = %d\n",
		PICL_PROP_CLASSNAME, error_code));
      return (error_code);
    }
    
    DEBUGMSG(("found %s of class %s\n",propname,propclass));
    
    if (strstr(propclass,"fan-tachometer"))
      process_individual_fan(childh,propname);
    else if (strstr(propclass,"temperature-sensor"))
      process_temperature_sensor(childh,propname);
    else if (strstr(propclass,"voltage-sensor"))
      process_voltage_sensor(childh,propname);
    else if (strstr(propclass,"digital-sensor"))
      process_digital_sensor(childh,propname);
    else if (strstr(propclass,"switch"))
      process_switch(childh,propname);
    else if (strstr(propclass,"led"))
      process_led(childh,propname);
    else if (strstr(propclass,"i2c"))
      process_i2c(childh,propname);
    // else if (strstr(propclass,"gpio"))
    //   process_gpio(childh,propname);

    /* look for children of children as long as this is not the fru tree */
    /* (note, this is recursive) */

    if (!(strstr(propclass,"picl") && 
	  (strstr(propname,"frutree") || strstr(propname,"obp")))) {
      error_code = process_sensors(childh);
      DEBUGMSG(("process_sensors(%s) returned %d\n", propname, error_code ));
    }
    
    /* get next child node at this level*/
    error_code = picl_get_propval_by_name(childh, PICL_PROP_PEER,
					  &nexth, sizeof (picl_nodehdl_t));
    if (error_code != PICL_SUCCESS) {/* no more children - buh bye*/
      DEBUGMSG(("Out of children!  Returning...\n"));
      return (error_code);
    }
    
    childh = nexth;
    
  } /* while */

  return (error_code);
}

//#############################################################################
 
static int process_individual_fan(picl_nodehdl_t childh,
				  char propname[PICL_PROPNAMELEN_MAX])
{
  int value = 0;
  read_num_sensor(childh, "AtoDSensorValue", 1, &value);
  printf("%s: %d RPM\n", propname, value);
}

//#############################################################################

static int process_digital_sensor(picl_nodehdl_t childh,
                                  char propname[PICL_PROPNAMELEN_MAX])
{
  int value = 0;
  read_num_sensor(childh, "AtoDSensorValue", 1, &value);
  printf("%s: %d ?\n", propname, value);

}

//#############################################################################

static int process_switch(picl_nodehdl_t childh,
			  char propname[PICL_PROPNAMELEN_MAX])
{
  int value = 0;
  char *settings[]={"OFF","ON","NORMAL","LOCKED","UNKNOWN",
		    "DIAG","SECURE",NULL};

  read_enum_sensor(childh, settings, &value);
  printf("%s: %s (switch)\n", propname, settings[value]);
}

//#############################################################################

static int process_led(picl_nodehdl_t childh,
		       char propname[PICL_PROPNAMELEN_MAX])
{  
  int value = 0;
  char *settings[]={"OFF","ON","BLINK",NULL};

  read_enum_sensor(childh, settings, &value);
  printf("%s: %s (led)\n", propname, settings[value]);
}

//#############################################################################

static int process_i2c(picl_nodehdl_t childh,
		       char propname[PICL_PROPNAMELEN_MAX])
{
  int value = 0;
  char *settings[]={"OK",NULL};

  read_enum_sensor(childh, settings, &value);
  printf("%s: %s (i2c)\n", propname, settings[value]);
}

//#############################################################################

process_voltage_sensor(picl_nodehdl_t childh,
		       char propname[PICL_PROPNAMELEN_MAX])
{
  int value = 0;
  read_num_sensor(childh, "Voltage", 1000, &value);
  printf("%s: %d mV\n", propname, value);
}

//#############################################################################

static int
process_temperature_sensor(picl_nodehdl_t childh,
			   char propname[PICL_PROPNAMELEN_MAX])
{
  int value = 0;
  read_num_sensor(childh, "Temperature", 1000, &value);
  printf("%s: %d mC\n", propname, value);
}

//#############################################################################

static void 
debug (char *class, char *name, int val) {
  printf("%s: %s: %d\n", name, class, val);
}

//#############################################################################

static int
read_num_sensor(picl_nodehdl_t childh, char *prop ,int scale, int *value)
{
  picl_nodehdl_t  sensorh;
  picl_propinfo_t sensor_info;

  union valu {
    char buf[PICL_PROPSIZE_MAX];
    uint32_t us4;
    uint16_t us2;
    int32_t is4;
    int16_t is2;
    float f;
  } val;

  picl_errno_t    error_code;

  error_code = (picl_get_propinfo_by_name(childh, prop,
					  &sensor_info, &sensorh));

  if (error_code != PICL_SUCCESS) {
     DEBUGMSG(("sensor lookup failed  error code->%d\n", error_code));
     return(error_code);
  }

  //printf("%s: type=%d, size=%d\n", prop, sensor_info.type, sensor_info.size);
  
  error_code = picl_get_propval(sensorh, &val.buf, sensor_info.size);

  if (error_code != PICL_SUCCESS) {
    DEBUGMSG(("sensor value read error code->%d\n", error_code));
    return(error_code);
  }
    
  /* Can't make assumptions about the type or size of the value we get... */

  if  (sensor_info.type == PICL_PTYPE_FLOAT) {
    *value = (int)(val.f*scale);
  } else if (sensor_info.type == PICL_PTYPE_UNSIGNED_INT) {
    if (sensor_info.size == 2) {
      *value = (int)(val.us2 * scale);
    } else if (sensor_info.size == 4) {
      *value = (int)(val.us4 * scale);
    }
  } else if (sensor_info.type == PICL_PTYPE_INT) {
    if (sensor_info.size == 2) {
      *value = (int)(val.is2 * scale);
    } else if (sensor_info.size == 4) {
      *value = (int)(val.is4 * scale);
    }
  } else
    printf("Don't know how to handle data type %d\n", sensor_info.type);
  
  return(error_code);
}

//#############################################################################

static int
read_enum_sensor(picl_nodehdl_t childh, char **options, int *value)
{
  picl_nodehdl_t  sensorh;
  picl_propinfo_t sensor_info;

  char state[PICL_PROPSIZE_MAX];
  int i;

  picl_errno_t    error_code;

  error_code = (picl_get_propinfo_by_name(childh, "State",
					  &sensor_info, &sensorh));

  if (error_code != PICL_SUCCESS) {
     DEBUGMSG(("sensor lookup failed  error code->%d\n", error_code));
     return(error_code);
  }

  //printf("State: type=%d, size=%d\n", sensor_info.type, sensor_info.size);
  
  error_code = picl_get_propval(sensorh, state, sensor_info.size);

  if (error_code != PICL_SUCCESS) {
    DEBUGMSG(("sensor value read error code->%d\n", error_code));
    return(error_code);
  }

  //printf(" got '%s'\n", state);
  
  *value = 99;

  /* Use case-insensitive match to find the right value since platforms
     may return either. */

  for (i = 0; options[i] != NULL; i++){
    if (strncasecmp(state, options[i], strlen(options[i])) == 0){
      *value = i;
      break;
    } 
  }
}  
  


//#############################################################################

Reply via email to