/*****************************************************************
******************************************************************
***                                                            ***
***        (C)Copyright 2008, American Megatrends Inc.         ***
***                                                            ***
***                    All Rights Reserved                     ***
***                                                            ***
***       5555 Oakbrook Parkway, Norcross, GA 30093, USA       ***
***                                                            ***
***                     Phone 770.246.8600                     ***
***                                                            ***
******************************************************************
******************************************************************
******************************************************************
* 
* Filename: libipmi_sensor.c
*
******************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>



#include "libipmi_session.h"
#include "libipmi_errorcodes.h"
#include "libipmi_sensor.h"
#include "libipmi_AppDevice.h"
#include "libipmi_storlead_OEM.h"
#include "com_BmcType.h"
#include "com_IPMIDefs.h"
#include "com_IPMI_Storlead.h"
#include "com_IPMI_App.h"


#define PACKED __attribute__ ((packed))


#include "com_IPMI_SDRRecord.h"


#include "com_IPMI_SensorEvent.h"

/* 35.2 Get Device SDR Info Command */
uint16_t	IPMICMD_GetSDRInfo( IPMI20_UDS_SESSION_T *pUDSSession,
							uint8_t	*pReqGetSDRInfo,
							GetSDRInfoRes_T *pResGetSDRInfo,
							int timeout)
{
	uint16_t	wRet;
	uint32_t	dwResLen;

	dwResLen = MAX_RESPONSE_SIZE;
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
											NETFNLUN_IPMI_SENSOR, CMD_GET_DEV_SDR_INFO,
											(uint8_t*)pReqGetSDRInfo, sizeof(uint8_t),
											(uint8_t *)pResGetSDRInfo, &dwResLen,
											timeout);

	return wRet;
}

/* 35.3 Get Device SDR Command */
  uint16_t	IPMICMD_GetDevSDR( IPMI20_UDS_SESSION_T *pUDSSession,
										GetDevSDRReq_T	*pReqDevSDR,
										GetDevSDRRes_T	*pResDevSDR,
										uint32_t			*pOutBuffLen,
										int timeout)
{
	uint16_t	wRet;
	uint32_t	dwResLen;

	dwResLen = sizeof(GetDevSDRRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
											NETFNLUN_IPMI_SENSOR, CMD_GET_DEV_SDR,
											(uint8_t*)pReqDevSDR, sizeof(GetDevSDRReq_T),
											(uint8_t *)pResDevSDR, &dwResLen,
											timeout);

	*pOutBuffLen = dwResLen;

	return wRet;
}

/* 35.4 Reserve Device SDR Repository Command */
  uint16_t	IPMICMD_ReserveDevSDR( IPMI20_UDS_SESSION_T *pUDSSession,
										ReserveDevSDRRes_T *pResReserveDevSDR,
										int timeout)
{
	char	Req[20];
	uint16_t	wRet;
	uint32_t	dwResLen;

	dwResLen = sizeof(ReserveDevSDRRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
											NETFNLUN_IPMI_SENSOR, CMD_RESERVE_DEV_SDR_REPOSITORY,
											(uint8_t*)Req, 0,
											(uint8_t *)pResReserveDevSDR, &dwResLen,
											timeout);

	return wRet;
}

/* 35.5 Get Sensor Reading Factors Command */
  uint16_t	IPMICMD_GetSensorReadingFactor( IPMI20_UDS_SESSION_T *pUDSSession,
										GetSensorReadingFactorReq_T	*pReqGetSensorReadingFactor,
										GetSensorReadingFactorRes_T *pResGetSensorReadingFactor,
										int timeout)
{
	uint16_t	wRet;
	uint32_t	dwResLen;

	dwResLen = sizeof(GetSensorReadingFactorRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
											NETFNLUN_IPMI_SENSOR, CMD_GET_SENSOR_READING_FACTORS,
											(uint8_t*)pReqGetSensorReadingFactor, sizeof(GetSensorReadingFactorReq_T),
											(uint8_t *)pResGetSensorReadingFactor, &dwResLen,
											timeout);

	return wRet;
}

/* 35.6 Set Sensor Hysteresis Command */
  uint16_t	IPMICMD_SetSensorHysterisis( IPMI20_UDS_SESSION_T *pUDSSession,
										SetSensorHysterisisReq_T *pReqSetSensorHysterisis,
										SetSensorHysterisisRes_T *pResSetSensorHysterisis,
										int timeout)
{
	uint16_t	wRet;
	uint32_t	dwResLen;

	dwResLen = sizeof(SetSensorHysterisisRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
											NETFNLUN_IPMI_SENSOR, CMD_SET_SENSOR_HYSTERISIS,
											(uint8_t*)pReqSetSensorHysterisis, sizeof(SetSensorHysterisisReq_T),
											(uint8_t *)pResSetSensorHysterisis, &dwResLen,
											timeout);

	return wRet;
}

/* 35.7 Get Sensor Hysteresis Command */
  uint16_t	IPMICMD_GetSensorHysterisis( IPMI20_UDS_SESSION_T *pUDSSession,
										GetSensorHysterisisReq_T *pReqGetSensorHysterisis,
										GetSensorHysterisisRes_T *pResGetSensorHysterisis,
										int timeout)
{
	uint16_t	wRet;
	uint32_t	dwResLen;

	dwResLen = sizeof(GetSensorHysterisisRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
											NETFNLUN_IPMI_SENSOR, CMD_GET_SENSOR_HYSTERISIS,
											(uint8_t*)pReqGetSensorHysterisis, sizeof(GetSensorHysterisisReq_T),
											(uint8_t *)pResGetSensorHysterisis, &dwResLen,
											timeout);

	return wRet;
}

/* 35.8 Set Sensor Thresholds Command */
  uint16_t	IPMICMD_SetSensorThreshold( IPMI20_UDS_SESSION_T *pUDSSession,
										SetSensorThresholdReq_T *pReqSetSensorThreshold,
										SetSensorThresholdRes_T *pResSetSensorThreshold,
										int timeout)
{
	uint16_t	wRet;
	uint32_t	dwResLen;

	dwResLen = sizeof(SetSensorThresholdRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
											NETFNLUN_IPMI_SENSOR, CMD_SET_SENSOR_THRESHOLDS,
											(uint8_t*)pReqSetSensorThreshold, sizeof(SetSensorThresholdReq_T),
											(uint8_t *)pResSetSensorThreshold, &dwResLen,
											timeout);

	return wRet;
}

/* 35.9 Get Sensor Thresholds Command */
  uint16_t	IPMICMD_GetSensorThreshold( IPMI20_UDS_SESSION_T *pUDSSession,
										GetSensorThresholdReq_T *pReqGetSensorThreshold,
										GetSensorThresholdRes_T *pResGetSensorThreshold,
										int timeout)
{
	uint16_t	wRet;
	uint32_t	dwResLen;

	dwResLen = sizeof(GetSensorThresholdRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
											NETFNLUN_IPMI_SENSOR, CMD_GET_SENSOR_THRESHOLDS,
											(uint8_t*)pReqGetSensorThreshold, sizeof(GetSensorThresholdReq_T),
											(uint8_t *)pResGetSensorThreshold, &dwResLen,
											timeout);

	return wRet;
}

/* 35.10 Set Sensor Event Enable Command */
  uint16_t	IPMICMD_SetSensorEventEnable( IPMI20_UDS_SESSION_T *pUDSSession,
										SetSensorEventEnableReq_T *pReqSetSensorEventEnable,
										SetSensorEventEnableRes_T *pResSetSensorEventEnable,
										int timeout)
{
	uint16_t	wRet;
	uint32_t	dwResLen;

	dwResLen = sizeof(SetSensorEventEnableRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
											NETFNLUN_IPMI_SENSOR, CMD_SET_SENSOR_EVENT_ENABLE,
											(uint8_t*)pReqSetSensorEventEnable, sizeof(SetSensorEventEnableReq_T),
											(uint8_t *)pResSetSensorEventEnable, &dwResLen,
											timeout);

	return wRet;
}

/* 35.11 Get Sensor Event Enable Command */
  uint16_t	IPMICMD_GetSensorEventEnable( IPMI20_UDS_SESSION_T *pUDSSession,
										GetSensorEventEnableReq_T *pReqGetSensorEventEnable,
										GetSensorEventEnableRes_T *pResGetSensorEventEnable,
										int timeout)
{
	uint16_t	wRet;
	uint32_t	dwResLen;

	dwResLen = sizeof(GetSensorEventEnableRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
											NETFNLUN_IPMI_SENSOR, CMD_GET_SENSOR_EVENT_ENABLE,
											(uint8_t*)pReqGetSensorEventEnable, sizeof(GetSensorEventEnableReq_T),
											(uint8_t *)pResGetSensorEventEnable, &dwResLen,
											timeout);

	return wRet;
}


/* 35.12 ReArm Sensor Events Command */
  uint16_t	IPMICMD_ReArmSensorEvents( IPMI20_UDS_SESSION_T *pUDSSession,
										ReArmSensorReq_T *pReArmSensorReq,
										ReArmSensorRes_T *pReArmSensorRes,
										int timeout)
{
	uint16_t	wRet;
	uint32_t	dwResLen;

	dwResLen = sizeof(ReArmSensorRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
											NETFNLUN_IPMI_SENSOR, CMD_REARM_SENSOR_EVENTS,
											(uint8_t*)pReArmSensorReq, sizeof(ReArmSensorReq_T),
											(uint8_t *)pReArmSensorRes, &dwResLen,
											timeout);

	return wRet;
}


/* 35.13 Get Sensor Event Status Command */
  uint16_t	IPMICMD_GetSensorEventStatus( IPMI20_UDS_SESSION_T *pUDSSession,
										GetSensorEventStatusReq_T *pReqGetSensorEventStatus,
										GetSensorEventStatusRes_T *pResGetSensorEventStatus,
										int timeout)
{
	uint16_t	wRet;
	uint32_t	dwResLen;

	dwResLen = sizeof(GetSensorEventStatusRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
											NETFNLUN_IPMI_SENSOR, CMD_GET_SENSOR_EVENT_STATUS,
											(uint8_t*)pReqGetSensorEventStatus, sizeof(GetSensorEventEnableReq_T),
											(uint8_t *)pResGetSensorEventStatus, &dwResLen,
											timeout);

	return wRet;
}

/* 35.14 Get Sensor Reading Command */
  uint16_t	IPMICMD_GetSensorReading( IPMI20_UDS_SESSION_T *pUDSSession,
										GetSensorReadingReq_T *pReqGetSensorReading,
										GetSensorReadingRes_T *pResGetSensorReading,
										int timeout)
{
	uint16_t	wRet;
	uint32_t	dwResLen;

	dwResLen = sizeof(GetSensorReadingRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
											NETFNLUN_IPMI_SENSOR, CMD_GET_SENSOR_READING,
											(uint8_t*)pReqGetSensorReading, sizeof(GetSensorReadingReq_T),
											(uint8_t *)pResGetSensorReading, &dwResLen,
											timeout);

	return wRet;
}

/* 35.15 Set Sensor Type Command */
  uint16_t	IPMICMD_SetSensorType( IPMI20_UDS_SESSION_T *pUDSSession,
										SetSensorTypeReq_T *pReqSetSensorType,
										SetSensorTypeRes_T *pResSetSensorType,
										int timeout)
{
	uint16_t	wRet;
	uint32_t	dwResLen;

	dwResLen = sizeof(SetSensorTypeRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
											NETFNLUN_IPMI_SENSOR, CMD_GET_SENSOR_READING,
											(uint8_t*)pReqSetSensorType, sizeof(SetSensorTypeReq_T),
											(uint8_t *)pResSetSensorType, &dwResLen,
											timeout);

	return wRet;
}


/* 35.16 Get Sensor Type Command */
  uint16_t	IPMICMD_GetSensorType( IPMI20_UDS_SESSION_T *pUDSSession,
										GetSensorTypeReq_T *pReqGetSensorType,
										GetSensorTypeRes_T *pResGetSensorType,
										int timeout)
{
	uint16_t	wRet;
	uint32_t	dwResLen;

	dwResLen = sizeof(GetSensorTypeRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
											NETFNLUN_IPMI_SENSOR, CMD_GET_SENSOR_READING,
											(uint8_t*)pReqGetSensorType, sizeof(GetSensorTypeReq_T),
											(uint8_t *)pResGetSensorType, &dwResLen,
											timeout);

	return wRet;
}
  uint16_t IPMICMD_SetSensorReading( IPMI20_UDS_SESSION_T *pUDSSession,
                                            SetSensorReadingReq_T *pReqSetSensorReading,
                                            SetSensorReadingRes_T *pResSetSensorReading,
                                            int timeout)
{
    uint16_t	wRet;
    uint32_t	dwResLen;

    dwResLen = sizeof(SetSensorReadingRes_T);
    wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
                                            NETFNLUN_IPMI_SENSOR,CMD_SET_SENSOR_READING,
                                            (uint8_t*)pReqSetSensorReading, sizeof(SetSensorReadingReq_T),
                                            (uint8_t *)pResSetSensorReading , &dwResLen,
                                             timeout);

    return wRet;
}



/* ------------------ High level functions ------------------ */
//#define SDR_FILE_PATH   "/tmp/sdr_data"

  uint16_t
LIBIPMI_HL_ReadSensorFromSDR( IPMI20_UDS_SESSION_T *pUDSSession, uint8_t *sdr_buffer,
							  uint8_t *raw_reading, float *reading,
							  uint8_t *discrete, int timeout )
{
 //    SDRRecHdr_T *header = (SDRRecHdr_T *)sdr_buffer;
 //    uint8_t SendMsg= FALSE;
 //    GetSensorReadingReq_T get_reading_req;
 //    GetSensorReadingRes_T get_reading_res;
 //    AMIGetChNumRes_T pAMIGetChNumRes;	
 //    uint8_t SendMsgReq[5]; 
 //    uint32_t SendMsgReqLen = 0;
 //    uint8_t record_type;
 //    uint16_t wRet;

 //    *discrete = (u8)0;

 //    record_type = header->Type;
	// if( record_type == 0x01 )
 //    {
 //        FullSensorRec_T *record;

 //        /* Determine if sensor is discrete, and pull out the sensor number */
 //        record = (FullSensorRec_T *)sdr_buffer;
 //        if( record->EventTypeCode > 0x01 )
 //            *discrete = record->EventTypeCode;
 //        if(record->OwnerID != 0x20)
 //        {
 //            wRet = IPMICMD_AMIGetChNum (pUDSSession,&pAMIGetChNumRes,
 //                                                                    timeout);
 //            SendMsg = TRUE;
 //            SendMsgReq[0] = 0x40 | pAMIGetChNumRes.ChannelNum;
 //            SendMsgReq[1] = record->OwnerID;
 //            SendMsgReq[2] = NETFN_SENSOR;
 //            SendMsgReq[3] = CMD_GET_SENSOR_READING;
 //            SendMsgReq[4] = record->SensorNum;
 //            SendMsgReqLen = 5;
 //        }
 //        else
 //        {
 //            get_reading_req.SensorNum = record->SensorNum;
 //        }        
 //    }
 //    else if( record_type == 0x02 )
 //    {
 //        CompactSensorRec_T *record;

 //        /* Determine if sensor is discrete, and pull out the sensor number */
 //        record = (CompactSensorRec_T *)sdr_buffer;
 //        if( record->EventTypeCode > 0x01 )
 //            *discrete = record->EventTypeCode;
 //        if(record->OwnerID != 0x20)
 //        {
 //            wRet = IPMICMD_AMIGetChNum (pUDSSession,&pAMIGetChNumRes,
 //                                                                    timeout);        
 //            SendMsg = TRUE;
 //            SendMsgReq[0] = 0x40 | pAMIGetChNumRes.ChannelNum;
 //            SendMsgReq[1] = record->OwnerID;
 //            SendMsgReq[2] = NETFN_SENSOR;
 //            SendMsgReq[3] = CMD_GET_SENSOR_READING;
 //            SendMsgReq[4] = record->SensorNum;
 //            SendMsgReqLen = 5;
 //        }
 //        else
 //        {
 //            get_reading_req.SensorNum = record->SensorNum;
 //        }       
 //    }
 //    else
 //    {
 //        /* We only know how to read sensors with records */
 //        /* of type full or compact                       */
 //        return( STATUS_CODE( IPMI_ERROR_FLAG, OEMCC_INVALID_SDR_ENTRY ) );
 //    }
     
 //    if(SendMsg == TRUE)
 //    {
 //        /*SendMessage Command to Get Sensor Reading when sensor Owner ID is not 0x20 */
 //        wRet = IPMICMD_SendMessage(pUDSSession,SendMsgReq,(uint8_t *)&get_reading_res,
 //                                                           SendMsgReqLen,timeout);
        
 //        if(get_reading_res.CompletionCode == CC_TIMEOUT)
 //        {
 //             get_reading_res.Flags &= 0x20;
 //        }
 //        else if( wRet != LIBIPMI_E_SUCCESS)
 //        {
 //            return( wRet );
 //        }    
        
 //    }
 //    else
 //    {
 //        /* Get the sensor reading */
 //        wRet = IPMICMD_GetSensorReading( pUDSSession, &get_reading_req,
 //                                     &get_reading_res, timeout );
 //        if( wRet != LIBIPMI_E_SUCCESS )
 //        {
 //            //printf("falied when readinf sensor no %d\n",get_reading_req.SensorNum);
 //            return( wRet );
 //        }
 //    }
 //    /* Pass the raw reading out to the caller. */
 //    /* We need this for discrete sensors.      */
 //    *raw_reading = get_reading_res.SensorReading;

 //    /* If sensor scanning is disabled or the reading is unavailable... */
 //    if( !( get_reading_res.Flags & 0x40 )  ||  ( get_reading_res.Flags & 0x20) )
 //    {
 //        /* Return an error code to let the caller know */
 //        return( STATUS_CODE( IPMI_ERROR_FLAG, OEMCC_SENSOR_DISABLED ) );
 //    }

 //    if( *discrete )
 //    {
 //        /* Pass the discrete state information back in the reading variable */
 //        *reading = (float)( get_reading_res.ComparisonStatus |
 //                            ( get_reading_res.OptionalStatus << 8 ) );
 //    }
 //    else
 //    {
 //        /* Convert raw sensor reading to final form */
 //        ipmi_convert_reading( sdr_buffer, *raw_reading, reading );
 //    }

    return( LIBIPMI_E_SUCCESS );
}


  uint16_t
LIBIPMI_HL_LoadSensorSDRs( IPMI20_UDS_SESSION_T *pUDSSession, uint8_t **sdr_buffer, 
                           int *count, int timeout )
{
    // FILE *sdrfile;
    // uint8_t *local_sdr_buffer = NULL;
    
    // /* Open the SDR file */
    // sdrfile = fopen( SDR_FILE_PATH, "r" );
    // if( sdrfile == NULL )
    // {
    //     /* If sdr file does not exist...    */
    //     if( errno == ENOENT )
    //     {
    //         /* ...create it */
    //         sdrfile = fopen( SDR_FILE_PATH, "w+" );
    //         if( sdrfile == NULL )
    //         {
    //             /* Uh-oh, something bad happened. */
    //             printf( "Cannot create SDR file: %s\n", strerror( errno ) );
    //             return( STATUS_CODE( IPMI_ERROR_FLAG, OEMCC_FILE_ERR ) );
    //         }

    //         /* Read the SDRs from the BMC (Note: this function calls malloc) */
    //         *count = read_sensor_sdrs( pUDSSession,
    //                                    (struct sensor_info **)&local_sdr_buffer,
    //                                    timeout );
    //         if( *count < 0 )
    //         {
    //             printf( "Cannot read SDRs from BMC: %s\n", strerror( errno ) );
    //             fclose( sdrfile );
    //             return( STATUS_CODE( IPMI_ERROR_FLAG, OEMCC_FILE_ERR ) );
    //         }

    //         /* Write the SDR data to file */
    //         if( fwrite( local_sdr_buffer, (size_t)1,
    //                     sizeof( struct sensor_info ) * *count, sdrfile ) < 0 )
    //         {
    //             printf( "Cannot write to SDR file: %s\n", strerror( errno ) );
    //             fclose( sdrfile );
    //             return( STATUS_CODE( IPMI_ERROR_FLAG, OEMCC_FILE_ERR ) );
    //         }

    //         fclose( sdrfile );
    //     }
    //     else
    //     {
    //         /* Uh-oh, something bad happened. */
    //         printf( "Cannot open SDR file: %s\n", strerror( errno ) );
    //         return( STATUS_CODE( IPMI_ERROR_FLAG, OEMCC_FILE_ERR ) );
    //     }
    // }
    // else
    // {
    //     int retval;
    //     size_t filelen;

    //     /* Determine the length of the file */
    //     retval = fseek( sdrfile, 0, SEEK_END );
    //     if( retval < 0 )
    //     {
    //         printf( "Cannot seek SDR file: %s\n", strerror( errno ) );
    //         fclose( sdrfile );
    //         return( STATUS_CODE( IPMI_ERROR_FLAG, OEMCC_FILE_ERR ) );
    //     }
    //     filelen = (size_t)ftell( sdrfile );

    //     /* If the caller actually wants the sdrs... */
    //     if( sdr_buffer != NULL )
    //     {
    //         /* Allocate some memory for 'em, and copy them in */
    //         local_sdr_buffer = malloc( filelen );
    //         if( local_sdr_buffer == NULL )
    //         {
    //             printf( "Cannot allocate memory for SDR file: %s\n", strerror( errno ) );
    //             fclose( sdrfile );
    //             return( STATUS_CODE( IPMI_ERROR_FLAG, OEMCC_NOMEM ) );
    //         }

    //         /* Back to the beginning of the file (after seeking to the end above) */
    //         retval = fseek( sdrfile, 0, SEEK_SET );
    //         if( retval < 0 )
    //         {
    //             printf( "Cannot seek SDR file: %s\n", strerror( errno ) );
    //             fclose( sdrfile );
    //             free( local_sdr_buffer );
    //             return( STATUS_CODE( IPMI_ERROR_FLAG, OEMCC_FILE_ERR ) );
    //         }

    //         /* Read the entire file into the buffer we allocated */
    //         if( fread( local_sdr_buffer, (size_t)1, filelen, sdrfile ) != filelen )
    //         {
    //             printf( "Cannot read from SDR file: %s\n", strerror( errno ) );
    //             fclose( sdrfile );
    //             free( local_sdr_buffer );
    //             return( STATUS_CODE( IPMI_ERROR_FLAG, OEMCC_FILE_ERR ) );
    //         }
    //     }

    //     fclose( sdrfile );

    //     /* Size of sensor info structs is regular, so it's easy to */
    //     /* calculate the number of SDRs in the file                */
    //     *count = filelen / sizeof( struct sensor_info );
    // }

    // /* If sdr_buffer is not null, pass a pointer to the allocated */
    // /* storage that contains the sdr data.                        */
    // if( sdr_buffer != NULL )
    //     *sdr_buffer = local_sdr_buffer;
    // else
    // {
    //     if( local_sdr_buffer != NULL )
    //         free( local_sdr_buffer );
    // }

    return( LIBIPMI_E_SUCCESS );   
}


uint16_t LIBIPMI_HL_GetSensorCount( IPMI20_UDS_SESSION_T *pUDSSession, int *sdr_count, int timeout )
{
    uint8_t    	Req[20];
    uint8_t 	Res[50];
    uint16_t    wRet;
    uint32_t    dwResLen;

    wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
                                            NETFNLUN_IPMI_STORAGE, CMD_GET_SDR_REPOSITORY_INFO,
                                            Req, 0,
                                            Res, &dwResLen,
                                            timeout);
    if((wRet != LIBIPMI_E_SUCCESS) || (Res[0] != 0))
    {
        printf("Error in Getting Num of Sensor infor\n");
        *sdr_count = 0;
        return wRet;
    }

    *sdr_count = (Res[3]<<8) | Res[2];
    return 0;
}

uint16_t IPMC_GetSensorCount( IPMI20_UDS_SESSION_T *pUDSSession, uint8_t IpmbAddr, int *sdr_count, int timeout )
{
    int wRet = 0;
	uint32_t	dwResLen;
	uint8_t 	Req[10] = {0};
	uint8_t		Res[50] = {0};

	Req[0] = 0x40;	//Track | channel 0
	Req[1] = IpmbAddr;
	Req[2] = NETFNLUN_IPMI_STORAGE;
	Req[3] = 0x100 - (Req[1] + Req[2])&0xff;	//checksum1
	Req[4] = 0x20;
	Req[5] = 0x10;
	Req[6] = CMD_GET_SDR_REPOSITORY_INFO;	
	Req[7] = 0x100 - (Req[4] + Req[5] + Req[6])&0xff;

	//dwResLen = sizeof(GetDevIDRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession, 
											DEFAULT_NET_FN_LUN, CMD_SEND_MSG,
											Req, 8,
											Res, &dwResLen,
											timeout);

    if((wRet != LIBIPMI_E_SUCCESS) || (Res[6] != 0))
    {
        printf("Error in Getting Num of Sensor infor\n");
        *sdr_count = 0;
        return wRet;
    }

    *sdr_count = (Res[9]<<8) | Res[8];
    return 0;
}

  uint16_t	LIBIPMI_HL_GetSensorReadingFactors( IPMI20_UDS_SESSION_T *pUDSSession,
										GetSensorReadingFactorReq_T	*pReqGetSensorReadingFactor,
										GetSensorReadingFactorRes_T *pResGetSensorReadingFactor,
										uint32_t* nNumSensor,
										int timeout)
{
	uint16_t	wRet;
	uint32_t	dwResLen;

	dwResLen = sizeof(GetSensorReadingFactorRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession, 
		                                     
											NETFNLUN_IPMI_SENSOR, 
											CMD_GET_SENSOR_READING_FACTORS,
											(uint8_t*)pReqGetSensorReadingFactor, 
											sizeof(GetSensorReadingFactorReq_T),
											(uint8_t *)pResGetSensorReadingFactor, 
											&dwResLen,
											timeout);
	

	return wRet;
}

uint16_t LIBIPMI_HL_GetAllSensorReadings( IPMI20_UDS_SESSION_T *pUDSSession, struct sensor_data *sensor_list, uint32_t nNumSensor, int timeout )
{
    uint16_t wRet;
    int sdr_count;
    int i ;
  	uint8_t Req[20];
  	StorleadGetSensorInfoRes_T GetSensorInfoRes; 
  	uint32_t dwResLen;
  	SenInfo_T *pSensorBuff;
  	float tmp_float;
  	uint16_t tmp_hw;

    for(i = 0; i < nNumSensor; i++)
    {
    	Req[0] = i;
		wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession, 	//notice!
						(NETFN_STORLEAD << 2), CMD_GET_SENSOR_INFO,
						Req, 1,
						(uint8_t*)&GetSensorInfoRes, &dwResLen,
						timeout);
		if(wRet == LIBIPMI_E_SUCCESS)
		{
			pSensorBuff = &GetSensorInfoRes.SensorInfo;
			sensor_list[ i ].sensor_num = pSensorBuff->SensorNumber;
	        sensor_list[ i ].owner_id = pSensorBuff->OwnerID;
	        sensor_list[ i ].owner_lun = pSensorBuff->OwnerLUN;
	        sensor_list[ i ].sensor_type = pSensorBuff->SensorTypeCode;
	        sensor_list[ i ].sensor_units[ 0 ] = pSensorBuff->Units1;
	        sensor_list[ i ].sensor_units[ 1 ] = pSensorBuff->Units2;
	        sensor_list[ i ].sensor_units[ 2 ] = pSensorBuff->Units3;
	        sensor_list[ i ].raw_reading = pSensorBuff->SensorReading;
	        strncpy(sensor_list[ i ].sensor_name,pSensorBuff->SensorName,MAX_ID_STR_LEN);
	        sensor_list[i].SensorAccessibleFlags = 0;

	        if(pSensorBuff->EventTypeCode > 1)
	        {
	            /*Updating the discrete sensor details*/
	            sensor_list[i].discrete_state = pSensorBuff->EventTypeCode;
	            sensor_list[i].sensor_state = 0;
	            sensor_list[ i ].sensor_reading = (float)(pSensorBuff->ComparisonStatus | (pSensorBuff->OptionalStatus << 8));
	        }
	        else
	        {
	            sensor_list[ i ].discrete_state = 0;
	            sensor_list[ i ].Settable_Readable_ThreshMask=pSensorBuff->Settable_Readable_ThreshMask;
	            
	            //if(pSensorBuff->SensorReading>0)
	            /*Convert Sensor Reading*/
	            ipmi_conv_reading(pSensorBuff->hdr.Type,pSensorBuff->SensorReading, &tmp_float, pSensorBuff->MinReading, pSensorBuff->MaxReading, pSensorBuff->Units1, 
	                                    pSensorBuff->Linearization, pSensorBuff->M_LSB, pSensorBuff->B_LSB, pSensorBuff->M_MSB_Tolerance, pSensorBuff->B_MSB_Accuracy,pSensorBuff->RExp_BExp);
	        	sensor_list[i].sensor_reading = tmp_float;

	            /*Convert LowerNonRecoverable*/
	            if(sensor_list[ i ].Settable_Readable_ThreshMask & BIT2)
	            ipmi_conv_reading(pSensorBuff->hdr.Type,pSensorBuff->LowerNonRecoverable, &tmp_float, pSensorBuff->MinReading, pSensorBuff->MaxReading, pSensorBuff->Units1, 
	                                    pSensorBuff->Linearization, pSensorBuff->M_LSB, pSensorBuff->B_LSB, pSensorBuff->M_MSB_Tolerance, pSensorBuff->B_MSB_Accuracy,pSensorBuff->RExp_BExp);
	        	sensor_list[i].low_non_recov_thresh = tmp_float;

	            /*Convert LowerCritical*/
	            if(sensor_list[ i ].Settable_Readable_ThreshMask & BIT1)
	            ipmi_conv_reading(pSensorBuff->hdr.Type,pSensorBuff->LowerCritical, &tmp_float, pSensorBuff->MinReading, pSensorBuff->MaxReading, pSensorBuff->Units1, 
	                                    pSensorBuff->Linearization, pSensorBuff->M_LSB, pSensorBuff->B_LSB, pSensorBuff->M_MSB_Tolerance, pSensorBuff->B_MSB_Accuracy,pSensorBuff->RExp_BExp);
	        	sensor_list[i].low_crit_thresh = tmp_float;

	            /*Convert LowerNonCritical*/
	            if(sensor_list[ i ].Settable_Readable_ThreshMask & BIT0)
	            ipmi_conv_reading(pSensorBuff->hdr.Type,pSensorBuff->LowerNonCritical, &tmp_float, pSensorBuff->MinReading, pSensorBuff->MaxReading, pSensorBuff->Units1, 
	                                    pSensorBuff->Linearization, pSensorBuff->M_LSB, pSensorBuff->B_LSB, pSensorBuff->M_MSB_Tolerance, pSensorBuff->B_MSB_Accuracy,pSensorBuff->RExp_BExp);
	        	sensor_list[i].low_non_crit_thresh = tmp_float;

	            /*Convert UpperNonCritical*/
	            if(sensor_list[ i ].Settable_Readable_ThreshMask & BIT3)
	            ipmi_conv_reading(pSensorBuff->hdr.Type,pSensorBuff->UpperNonCritical, &tmp_float, pSensorBuff->MinReading, pSensorBuff->MaxReading, pSensorBuff->Units1, 
	                                    pSensorBuff->Linearization, pSensorBuff->M_LSB, pSensorBuff->B_LSB, pSensorBuff->M_MSB_Tolerance, pSensorBuff->B_MSB_Accuracy,pSensorBuff->RExp_BExp);
	        	sensor_list[i].high_non_crit_thresh = tmp_float;

	            /*Convert UpperCritical*/
	            if(sensor_list[ i ].Settable_Readable_ThreshMask & BIT4)
	            ipmi_conv_reading(pSensorBuff->hdr.Type,pSensorBuff->UpperCritical, &tmp_float, pSensorBuff->MinReading, pSensorBuff->MaxReading, pSensorBuff->Units1, 
	                                    pSensorBuff->Linearization, pSensorBuff->M_LSB, pSensorBuff->B_LSB, pSensorBuff->M_MSB_Tolerance, pSensorBuff->B_MSB_Accuracy,pSensorBuff->RExp_BExp);
	        	sensor_list[i].high_crit_thresh = tmp_float;

	            /*Convert UpperNonRecoverable*/
	            if(sensor_list[ i ].Settable_Readable_ThreshMask & BIT5)
	            ipmi_conv_reading(pSensorBuff->hdr.Type,pSensorBuff->UpperNonRecoverable, &tmp_float, pSensorBuff->MinReading, pSensorBuff->MaxReading, pSensorBuff->Units1, 
	                                    pSensorBuff->Linearization, pSensorBuff->M_LSB, pSensorBuff->B_LSB, pSensorBuff->M_MSB_Tolerance, pSensorBuff->B_MSB_Accuracy,pSensorBuff->RExp_BExp);
	        	sensor_list[i].high_non_recov_thresh = tmp_float;

	        	//MAX reading
	        	if(sensor_list[ i ].Settable_Readable_ThreshMask & BIT5)
	            ipmi_conv_reading(pSensorBuff->hdr.Type,pSensorBuff->MaxReading, &tmp_float, pSensorBuff->MinReading, pSensorBuff->MaxReading, pSensorBuff->Units1, 
	                                    pSensorBuff->Linearization, pSensorBuff->M_LSB, pSensorBuff->B_LSB, pSensorBuff->M_MSB_Tolerance, pSensorBuff->B_MSB_Accuracy,pSensorBuff->RExp_BExp);
	        	sensor_list[i].max_reading = tmp_float;

	        	//MIN reading
	        	if(sensor_list[ i ].Settable_Readable_ThreshMask & BIT5)
	            ipmi_conv_reading(pSensorBuff->hdr.Type,pSensorBuff->MinReading, &tmp_float, pSensorBuff->MinReading, pSensorBuff->MaxReading, pSensorBuff->Units1, 
	                                    pSensorBuff->Linearization, pSensorBuff->M_LSB, pSensorBuff->B_LSB, pSensorBuff->M_MSB_Tolerance, pSensorBuff->B_MSB_Accuracy,pSensorBuff->RExp_BExp);
	        	sensor_list[i].min_reading = tmp_float;

	            /*Get the Sensor state*/
	            SensorState(pSensorBuff->SensorReading,&tmp_hw,pSensorBuff->hdr.Type,pSensorBuff->Linearization,pSensorBuff->Units1,pSensorBuff->EventTypeCode,pSensorBuff->AssertionEventByte1,pSensorBuff->AssertionEventByte2,pSensorBuff->DeassertionEventByte1,pSensorBuff->DeassertionEventByte2);
	            sensor_list[i].sensor_state = tmp_hw;
            }

	        /* If sensor scanning is disabled or the reading is unavailable... */
	        if( !( pSensorBuff->Flags & SENSOR_SCANNING_BIT)  || (pSensorBuff->Flags & UNABLE_TO_READ_SENSOR) )
	        {
	            /* Return an error code to let the caller know */
	            sensor_list[i].SensorAccessibleFlags = SENSOR_NOT_AVAILABLE;
	            sensor_list[i].sensor_reading = 0;
	            sensor_list[i].discrete_state = 0;
	            sensor_list[i].raw_reading = 0;
	        }

	        //printf("sensor_list[%d]: SensorNum %d, SensorName %s, SensorReading = %f\n", i, sensor_list[i].sensor_num, sensor_list[i].sensor_name, sensor_list[i].sensor_reading);
		}
		else
		{
			printf("error getting sensor info %d\n",wRet);
		}
    }
    return wRet ;
}


uint16_t IPMC_GetAllSensorReadings( IPMI20_UDS_SESSION_T *pUDSSession, uint8_t IpmbAddr, struct sensor_data *sensor_list, uint32_t nNumSensor, int timeout )
{

    int sdr_count;
    int i ;
  	StorleadGetSensorInfoRes_T *pGetSensorInfoRes; 
  	SenInfo_T *pSensorBuff;
  	float tmp_float;
  	uint16_t tmp_hw;

	int wRet = 0;
	uint32_t	dwResLen;
	uint8_t 	Req[10] = {0};
	uint8_t		Res[100] = {0};

	Req[0] = 0x40;	//Track | channel 0
	Req[1] = IpmbAddr;
	Req[2] = NETFNLUN_IPMI_STORLEAD;
	Req[3] = 0x100 - (Req[1] + Req[2])&0xff;	//checksum1
	Req[4] = 0x20;
	Req[5] = 0x10;
	Req[6] = CMD_GET_SENSOR_INFO;	
	Req[7] = 0;
	Req[8] = 0x100 - (Req[4] + Req[5] + Req[6] + Req[7])&0xff;

    for(i = 0; i < nNumSensor; i++)
    {
    	Req[7] = i;
		Req[8] = 0x100 - (Req[4] + Req[5] + Req[6] + Req[7])&0xff;    	
		wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession, 	//notice!
						DEFAULT_NET_FN_LUN, CMD_SEND_MSG,
						Req, 9,
						Res, &dwResLen,
						timeout);
		//printf("---> i = %d, ccode = %d\n", i, Res[6]);
		if((wRet == LIBIPMI_E_SUCCESS) && (Res[6] == 0))
		{
			pGetSensorInfoRes = (StorleadGetSensorInfoRes_T*)&Res[6];
			pSensorBuff = &pGetSensorInfoRes->SensorInfo;
			sensor_list[ i ].sensor_num = pSensorBuff->SensorNumber;
	        sensor_list[ i ].owner_id = pSensorBuff->OwnerID;
	        sensor_list[ i ].owner_lun = pSensorBuff->OwnerLUN;
	        sensor_list[ i ].sensor_type = pSensorBuff->SensorTypeCode;
	        sensor_list[ i ].sensor_units[ 0 ] = pSensorBuff->Units1;
	        sensor_list[ i ].sensor_units[ 1 ] = pSensorBuff->Units2;
	        sensor_list[ i ].sensor_units[ 2 ] = pSensorBuff->Units3;
	        sensor_list[ i ].raw_reading = pSensorBuff->SensorReading;
	        strncpy(sensor_list[ i ].sensor_name,pSensorBuff->SensorName,MAX_ID_STR_LEN);
	        sensor_list[i].SensorAccessibleFlags = 0;

	        if(pSensorBuff->EventTypeCode > 1)
	        {
	            /*Updating the discrete sensor details*/
	            sensor_list[i].discrete_state = pSensorBuff->EventTypeCode;
	            sensor_list[i].sensor_state = 0;
	            sensor_list[ i ].sensor_reading = (float)(pSensorBuff->ComparisonStatus | (pSensorBuff->OptionalStatus << 8));
	        }
	        else
	        {
	            sensor_list[ i ].discrete_state = 0;
	            sensor_list[ i ].Settable_Readable_ThreshMask=pSensorBuff->Settable_Readable_ThreshMask;
	            
	            //if(pSensorBuff->SensorReading>0)
	            /*Convert Sensor Reading*/
	            ipmi_conv_reading(pSensorBuff->hdr.Type,pSensorBuff->SensorReading, &tmp_float, pSensorBuff->MinReading, pSensorBuff->MaxReading, pSensorBuff->Units1, 
	                                    pSensorBuff->Linearization, pSensorBuff->M_LSB, pSensorBuff->B_LSB, pSensorBuff->M_MSB_Tolerance, pSensorBuff->B_MSB_Accuracy,pSensorBuff->RExp_BExp);
	        	sensor_list[i].sensor_reading = tmp_float;

	            /*Convert LowerNonRecoverable*/
	            if(sensor_list[ i ].Settable_Readable_ThreshMask & BIT2)
	            ipmi_conv_reading(pSensorBuff->hdr.Type,pSensorBuff->LowerNonRecoverable, &tmp_float, pSensorBuff->MinReading, pSensorBuff->MaxReading, pSensorBuff->Units1, 
	                                    pSensorBuff->Linearization, pSensorBuff->M_LSB, pSensorBuff->B_LSB, pSensorBuff->M_MSB_Tolerance, pSensorBuff->B_MSB_Accuracy,pSensorBuff->RExp_BExp);
	        	sensor_list[i].low_non_recov_thresh = tmp_float;

	            /*Convert LowerCritical*/
	            if(sensor_list[ i ].Settable_Readable_ThreshMask & BIT1)
	            ipmi_conv_reading(pSensorBuff->hdr.Type,pSensorBuff->LowerCritical, &tmp_float, pSensorBuff->MinReading, pSensorBuff->MaxReading, pSensorBuff->Units1, 
	                                    pSensorBuff->Linearization, pSensorBuff->M_LSB, pSensorBuff->B_LSB, pSensorBuff->M_MSB_Tolerance, pSensorBuff->B_MSB_Accuracy,pSensorBuff->RExp_BExp);
	        	sensor_list[i].low_crit_thresh = tmp_float;

	            /*Convert LowerNonCritical*/
	            if(sensor_list[ i ].Settable_Readable_ThreshMask & BIT0)
	            ipmi_conv_reading(pSensorBuff->hdr.Type,pSensorBuff->LowerNonCritical, &tmp_float, pSensorBuff->MinReading, pSensorBuff->MaxReading, pSensorBuff->Units1, 
	                                    pSensorBuff->Linearization, pSensorBuff->M_LSB, pSensorBuff->B_LSB, pSensorBuff->M_MSB_Tolerance, pSensorBuff->B_MSB_Accuracy,pSensorBuff->RExp_BExp);
	        	sensor_list[i].low_non_crit_thresh = tmp_float;

	            /*Convert UpperNonCritical*/
	            if(sensor_list[ i ].Settable_Readable_ThreshMask & BIT3)
	            ipmi_conv_reading(pSensorBuff->hdr.Type,pSensorBuff->UpperNonCritical, &tmp_float, pSensorBuff->MinReading, pSensorBuff->MaxReading, pSensorBuff->Units1, 
	                                    pSensorBuff->Linearization, pSensorBuff->M_LSB, pSensorBuff->B_LSB, pSensorBuff->M_MSB_Tolerance, pSensorBuff->B_MSB_Accuracy,pSensorBuff->RExp_BExp);
	        	sensor_list[i].high_non_crit_thresh = tmp_float;

	            /*Convert UpperCritical*/
	            if(sensor_list[ i ].Settable_Readable_ThreshMask & BIT4)
	            ipmi_conv_reading(pSensorBuff->hdr.Type,pSensorBuff->UpperCritical, &tmp_float, pSensorBuff->MinReading, pSensorBuff->MaxReading, pSensorBuff->Units1, 
	                                    pSensorBuff->Linearization, pSensorBuff->M_LSB, pSensorBuff->B_LSB, pSensorBuff->M_MSB_Tolerance, pSensorBuff->B_MSB_Accuracy,pSensorBuff->RExp_BExp);
	        	sensor_list[i].high_crit_thresh = tmp_float;

	            /*Convert UpperNonRecoverable*/
	            if(sensor_list[ i ].Settable_Readable_ThreshMask & BIT5)
	            ipmi_conv_reading(pSensorBuff->hdr.Type,pSensorBuff->UpperNonRecoverable, &tmp_float, pSensorBuff->MinReading, pSensorBuff->MaxReading, pSensorBuff->Units1, 
	                                    pSensorBuff->Linearization, pSensorBuff->M_LSB, pSensorBuff->B_LSB, pSensorBuff->M_MSB_Tolerance, pSensorBuff->B_MSB_Accuracy,pSensorBuff->RExp_BExp);
	        	sensor_list[i].high_non_recov_thresh = tmp_float;

	        	//MAX reading
	        	if(sensor_list[ i ].Settable_Readable_ThreshMask & BIT5)
	            ipmi_conv_reading(pSensorBuff->hdr.Type,pSensorBuff->MaxReading, &tmp_float, pSensorBuff->MinReading, pSensorBuff->MaxReading, pSensorBuff->Units1, 
	                                    pSensorBuff->Linearization, pSensorBuff->M_LSB, pSensorBuff->B_LSB, pSensorBuff->M_MSB_Tolerance, pSensorBuff->B_MSB_Accuracy,pSensorBuff->RExp_BExp);
	        	sensor_list[i].max_reading = tmp_float;

	        	//MIN reading
	        	if(sensor_list[ i ].Settable_Readable_ThreshMask & BIT5)
	            ipmi_conv_reading(pSensorBuff->hdr.Type,pSensorBuff->MinReading, &tmp_float, pSensorBuff->MinReading, pSensorBuff->MaxReading, pSensorBuff->Units1, 
	                                    pSensorBuff->Linearization, pSensorBuff->M_LSB, pSensorBuff->B_LSB, pSensorBuff->M_MSB_Tolerance, pSensorBuff->B_MSB_Accuracy,pSensorBuff->RExp_BExp);
	        	sensor_list[i].min_reading = tmp_float;

	            /*Get the Sensor state*/
	            SensorState(pSensorBuff->SensorReading,&tmp_hw,pSensorBuff->hdr.Type,pSensorBuff->Linearization,pSensorBuff->Units1,pSensorBuff->EventTypeCode,pSensorBuff->AssertionEventByte1,pSensorBuff->AssertionEventByte2,pSensorBuff->DeassertionEventByte1,pSensorBuff->DeassertionEventByte2);
	            sensor_list[i].sensor_state = tmp_hw;
            }

	        /* If sensor scanning is disabled or the reading is unavailable... */
	        if( !( pSensorBuff->Flags & SENSOR_SCANNING_BIT)  || (pSensorBuff->Flags & UNABLE_TO_READ_SENSOR) )
	        {
	            /* Return an error code to let the caller know */
	            sensor_list[i].SensorAccessibleFlags = SENSOR_NOT_AVAILABLE;
	            sensor_list[i].sensor_reading = 0;
	            sensor_list[i].discrete_state = 0;
	            sensor_list[i].raw_reading = 0;
	        }

	        //printf("sensor_list[%d]: SensorNum %d, SensorName %s, SensorReading = %f\n", i, sensor_list[i].sensor_num, sensor_list[i].sensor_name, sensor_list[i].sensor_reading);
		}
		else
		{
			printf("error getting sensor info %d\n",wRet);
		}
    }
    return wRet ;
}