/*
 * Brief:	Get all sensor information.
 * Author:	Jimbo_zhang@outlook.com
 * Data:		2019-4-27
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "dbgout.h"
#include "libipmi_AppDevice.h"
#include "libipmi_AMIOEM.h"
#include "libipmi_session.h"
#include "libipmi_errorcodes.h"
#include "libipmi_struct.h"
#include "IPMI_AMIDevice.h"
#include "std_macros.h"
#include "IPMI_AMISmtp.h"
#include "AMIDevice.h"
#include "IPMI_AMIResetPass.h"
#include "IPMI_AMIConf.h"
#include "ncml.h"
#include "AMIRestoreDefaults.h"
#include "libipmi_StorDevice.h"
#include "SELRecord.h"
#include "SEL.h"
#include "IPMI_SEL.h"
#if LIBIPMI_IS_OS_LINUX()
#include <time.h>
#include <sys/types.h>
#include <pwd.h>
#include "pam_helper.h"
#endif
#include "coreTypes.h"
#include "libipmi_sdr.h"
#include "libipmi_sensor.h"
#include "libipmi_storlead_OEM.h"
#include "sensor_helpers.h"


OemWebFlags_T g_OemWebFlags;
/*
*@fn IPMICMD_AMIGetSensorInfo
*@brief
*@param pSession - IPMI Session Handle
*@param pAMIGetSensorInfoReq - Pointer to the request of AMI Get SensorInfo command
*@param pAMIGetSensorInfoRes - Pointer to the response of AMI Get SensorInfo command
*@param timeout - Timeout Value
**/
uint16_t IPMICMD_GetIPMCSensorInfo(IPMI20_SESSION_T *pSession, AMIGetSensorInfoRes_T *pGetIPMCSensorInfoRes,int timeout)
{
	uint16_t wRet = 0;
	
	uint16_t reservation_id;
	uint16_t record_id = 0;
	uint32_t dwRecordLen;
	SenInfo_T SensorInfo;
	
	uint8_t SDRData[100] = {0};
	uint8_t NextRecIDLS = 0;
	uint8_t NextRecIDMS = 0;
	uint8_t cnt = 0;
	uint8_t timeoutTick = 0;
	wRet = IPMICMD_ReserveSDRRepository(pSession, (ReserveSDRRepositoryRes_T*)SDRData, timeout);
	if(wRet != 0)
	{
		printf("Error Reserve SDR Repository\n");
		return wRet;
	}
	
	reservation_id = SDRData[2]<<8 | SDRData[1];
	
	do
	{
		//Get SDR
		if(0 != LIBIPMI_HL_GetSDR(pSession, reservation_id, record_id, (GetSDRRes_T*)SDRData, &dwRecordLen, timeout ))
		{
			printf("---> Get SDR error! record_id = %#x\n", record_id);
			return -1;
		}
			
		NextRecIDLS = SDRData[1];
		NextRecIDMS = SDRData[2];
		memcpy(&SensorInfo.hdr, &SDRData[3],5/*Sizeof(SDRRecHdr_T)*/);
		if(SensorInfo.hdr.Type == 0x01)	//full sensor sdr
		{	
			SensorInfo.Accuracy_MSB_Exp = SDRData[3+29-1];
			//SensorInfo.AssertionEventByte1 = SDRData[3+15-1];
			//SensorInfo.AssertionEventByte2 = SDRData[3+16-1];
			SensorInfo.B_LSB	= SDRData[3+27-1];
			SensorInfo.B_MSB_Accuracy	=	SDRData[3+28-1];
			SensorInfo.DeassertionEventByte1	=	SDRData[3+17-1];
			SensorInfo.DeassertionEventByte2	=	SDRData[3+18-1];
			SensorInfo.EventTypeCode	=	SDRData[3+14-1];
			SensorInfo.Linearization	=	SDRData[3+24-1];
			SensorInfo.LowerCritical	=	SDRData[3+41-1];
			SensorInfo.LowerNonCritical	=	SDRData[3+42-1];
			SensorInfo.LowerNonRecoverable	=	SDRData[3+40-1];
			SensorInfo.M_LSB	=	SDRData[3+25-1];
			SensorInfo.M_MSB_Tolerance	=	SDRData[3+26-1];
			SensorInfo.MaxReading	=	SDRData[3+35-1];
			SensorInfo.MinReading	=	SDRData[3+36-1];
			SensorInfo.OwnerID	=	SDRData[3+6-1];
			SensorInfo.OwnerLUN	=	SDRData[3+7-1];
			SensorInfo.RExp_BExp	=	SDRData[3+30-1];			
			SensorInfo.SensorNumber	=	SDRData[3+8-1];
			SensorInfo.SensorTypeCode		=	SDRData[3+13-1];
			SensorInfo.Settable_Readable_ThreshMask	=	SDRData[3+20-1]<<8 | SDRData[3+19-1];
			SensorInfo.Units1	=	SDRData[3+21-1];
			SensorInfo.Units2	=	SDRData[3+22-1];
			SensorInfo.Units3	=	SDRData[3+23-1];
			SensorInfo.UpperCritical	=	SDRData[3+38-1];
			SensorInfo.UpperNonCritical	=	SDRData[3+39-1];
			SensorInfo.UpperNonRecoverable = SDRData[3+37-1];
			
			memset(SensorInfo.SensorName, 0, 16);
			memcpy(SensorInfo.SensorName, &SDRData[3+49-1], SDRData[3+48-1]&0x3f);
			
			//get sensor reading
			if(0 != IPMICMD_GetSensorReading(pSession, (GetSensorReadingReq_T *)&SensorInfo.SensorNumber, 
				(GetSensorReadingRes_T *)SDRData, timeout))
			{
				printf("---> Get sensorReading error! sensorNum = %#x\n", SensorInfo.SensorNumber);
				return -1;
			}
			SensorInfo.SensorReading = SDRData[1];
			SensorInfo.OptionalStatus	=	SDRData[4];
			SensorInfo.Flags	=	SDRData[2];
			
			SensorInfo.ComparisonStatus = SDRData[3];
			if(SensorInfo.EventTypeCode == 0x01)	//threshold
			{
				//TODO: jimbo
				SensorInfo.AssertionEventByte1 = 0x0;
				SensorInfo.AssertionEventByte2 = 0x0;
				if((SensorInfo.Units1 & 0xc0) == 0x00)	//unsigned
				{
					if((uint8_t)SensorInfo.SensorReading > (uint8_t)SensorInfo.UpperCritical)
						SensorInfo.AssertionEventByte2 |= 0x02;
					if((uint8_t)SensorInfo.SensorReading > (uint8_t)SensorInfo.UpperNonCritical)
						SensorInfo.AssertionEventByte1 |= 0x80;
					if((uint8_t)SensorInfo.SensorReading > (uint8_t)SensorInfo.UpperNonRecoverable)
						SensorInfo.AssertionEventByte2 |= 0x08;
					if((uint8_t)SensorInfo.SensorReading < (uint8_t)SensorInfo.LowerCritical)
						SensorInfo.AssertionEventByte1 |= 0x04;
					if((uint8_t)SensorInfo.SensorReading < (uint8_t)SensorInfo.LowerNonCritical)
						SensorInfo.AssertionEventByte1 |= 0x01;
					if((uint8_t)SensorInfo.SensorReading < (uint8_t)SensorInfo.LowerNonRecoverable)
						SensorInfo.AssertionEventByte1 |= 0x10;					
				}
				else if((SensorInfo.Units1 & 0xc0) == 0x80)	//2's complement
				{
					if((int8)SensorInfo.SensorReading > (int8)SensorInfo.UpperCritical)
						SensorInfo.AssertionEventByte2 |= 0x02;
					if((int8)SensorInfo.SensorReading > (int8)SensorInfo.UpperNonCritical)
						SensorInfo.AssertionEventByte1 |= 0x80;
					if((int8)SensorInfo.SensorReading > (int8)SensorInfo.UpperNonRecoverable)
						SensorInfo.AssertionEventByte2 |= 0x08;
					if((int8)SensorInfo.SensorReading < (int8)SensorInfo.LowerCritical)
						SensorInfo.AssertionEventByte1 |= 0x04;
					if((int8)SensorInfo.SensorReading < (int8)SensorInfo.LowerNonCritical)
						SensorInfo.AssertionEventByte1 |= 0x01;
					if((int8)SensorInfo.SensorReading < (int8)SensorInfo.LowerNonRecoverable)
						SensorInfo.AssertionEventByte1 |= 0x10;
				}
				
			}
			
			
			memcpy(((uint8_t*)pGetIPMCSensorInfoRes)+3+sizeof(SenInfo_T)*cnt, &SensorInfo, sizeof(SenInfo_T));
			cnt++;
			
//			printf("cnt: %d, sensorNum: %#x, sensorReading: %#x, OptionStatus = %#x, ComparisonStatus = %#x\n", 
//					cnt, SensorInfo.SensorNumber, SensorInfo.SensorReading, SensorInfo.OptionalStatus, SensorInfo.ComparisonStatus);
		}
		
		
		record_id = NextRecIDMS<<8 | NextRecIDLS;
		timeoutTick++;
		if(timeoutTick > 64)	
		{
			wRet = -1;
			break;
		}
	}while(record_id != 0xffff);	  
	
	if(wRet == 0)
		pGetIPMCSensorInfoRes->CompletionCode = 0;
	else
		pGetIPMCSensorInfoRes->CompletionCode = 255;
	
	pGetIPMCSensorInfoRes->Noofentries = cnt;
	
//	printf("return pGetIPMCSensorInfoRes: ");
//	for(i=0;i<3+sizeof(SenInfo_T)*cnt;i++)
//		printf("%#2x ",((uint8_t*)pGetIPMCSensorInfoRes)[i]);
//	printf("\n");
	
	return (wRet);
}


uint16_t LIBIPMI_HL_GetIPMCSensorInfo(IPMI20_SESSION_T *pSession,SenInfo_T *pSensorInfo,uint32_t *nNumSensor,int timeout)
{
	uint16_t wRet = 0;
	AMIGetSensorInfoRes_T *pGetIPMCSensorInfoRes;
	uint8_t *SensorEntries;
	int i;
	
	SensorEntries = (uint8_t *)malloc(MAX_SENSOR_INFO_SIZE);
	if(SensorEntries == NULL)
	{
		printf("Memory allocation error in LIBIPMI_HL_AMIGetSELEntires \n");
		wRet = 0xFF;
		return wRet;
	}
	
	memset(SensorEntries,0,MAX_SENSOR_INFO_SIZE);
	pGetIPMCSensorInfoRes = (AMIGetSensorInfoRes_T *)SensorEntries;
	wRet = IPMICMD_GetIPMCSensorInfo(pSession,(AMIGetSensorInfoRes_T *)SensorEntries,timeout);
	if(wRet == LIBIPMI_E_SUCCESS)
	{
		*nNumSensor = pGetIPMCSensorInfoRes->Noofentries;
		for(i = 0; i < pGetIPMCSensorInfoRes->Noofentries; i++)
		{
			memcpy((uint8_t *)&pSensorInfo[i],&SensorEntries[sizeof(AMIGetSensorInfoRes_T) + (i * sizeof(SenInfo_T))],sizeof(SenInfo_T) );
		}
	}
	else
	{
		printf("error getting sensor info %d\n",wRet);
	}
	free(SensorEntries);
	return (wRet);
}

uint16_t LIBIPMI_HL_FanCtrol( IPMI20_SESSION_T *pSession, uint8_t fanIndex, uint8_t fanMode, uint8_t fanLevel, int timeout)
{
	uint16_t wRet = 0;
	uint8_t	Res[10];
	uint8_t Req[10];
	uint32_t dwResLen;
	Req[0]	= fanIndex;
	Req[1] 	= fanMode;
	Req[2]	= fanLevel;
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pSession, PAYLOAD_TYPE_IPMI, 0x2e<<2, 0x87,
													(uint8_t*)Req, 3,
													(uint8_t *)Res, &dwResLen,
													timeout);
	return wRet;
}

int LIBIPMI_HL_GetFanStatus( IPMI20_SESSION_T *pSession, uint8_t fanIndex, OemFanStatus_T *pFanStatus, int timeout)
{
	uint16_t wRet = 0;
	uint8_t	Res[32];
	uint32_t dwResLen;
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pSession, PAYLOAD_TYPE_IPMI, 0x2e<<2, 0x86,
														(uint8_t*)&fanIndex, 1,
														(uint8_t *)Res, &dwResLen,
														timeout);
	memset(pFanStatus->name, 0, 16);
	if((wRet == 0) && (Res[0] == 0))
	{
		pFanStatus->index = fanIndex;
		memcpy(pFanStatus->name, &Res[1], 16);
		pFanStatus->level = Res[17];
		pFanStatus->mode = Res[18];
		pFanStatus->speed = (Res[19]<<24) | (Res[20]<<16) | (Res[21]<<8) | Res[22];
	}
	else
	{
		printf("---> LIBIPMI_HL_GetFanInfo get fan info error!\n");
		pFanStatus->index = fanIndex;
		memcpy(pFanStatus->name, "UNKNOWN", 7);
		pFanStatus->level = 0;
		pFanStatus->mode = 0;
		pFanStatus->speed = 0;
		return -1;
	}
	
	return 0;	
}

uint16_t LIBIPMI_HL_GetExtraInfo( IPMI20_SESSION_T *pSession, ExtraInfo_T *extraInfo, int timeout)
{
	
	uint16_t wRet = 0;
	uint8_t Req[5];
	uint8_t	Res[MAX_TEXT_LEN+5];
	uint32_t dwResLen;
	uint16_t strLen, remainLen;
	uint16_t offset = 0;

	if(pSession->byMediumType == UDS_MEDIUM)
	{
		//get title
		Req[0] = 0;
		Req[1] = 0;
		Req[2] = 0;
		Req[3] = (MAX_TITLE_LEN>>8)&0xff;	//max title len
		Req[4] = MAX_TITLE_LEN&0xff;
		wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pSession, PAYLOAD_TYPE_IPMI, 0x2e<<2, 0x83,
																(uint8_t*)Req, 5,
																(uint8_t *)Res, &dwResLen,
																timeout);
		if((wRet != 0) || (Res[0] != 0))
		{
			printf("---> get Title error\n");
			return -1;
		}
		strLen = (Res[1]<<8) | Res[2];
		remainLen = (Res[3]<<8) | Res[4];
		memcpy(extraInfo->title,&Res[5],strLen);
		
		//get text
		Req[0] = 1;
		Req[1] = 0;
		Req[2] = 0;
		Req[3] = (MAX_TEXT_LEN>>8)&0xff;	//max text len
		Req[4] = MAX_TEXT_LEN&0xff;
		wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pSession, PAYLOAD_TYPE_IPMI, 0x2e<<2, 0x83,
																(uint8_t*)Req, 5,
																(uint8_t *)Res, &dwResLen,
																timeout);
		if((wRet != 0) || (Res[0] != 0))
		{
			printf("---> get Text error\n");
			return -1;
		}
		strLen = (Res[1]<<8) | Res[2];
		remainLen = (Res[3]<<8) | Res[4];
		memcpy(extraInfo->text,&Res[5],strLen);
	}
	else if(pSession->byMediumType == IPMB_MEDIUM)
	{
		//get title
		do{
			Req[0] = 0;
			Req[1] = (offset>>8)&0xff;
			Req[2] = offset&0xff;
			Req[3] = 0;	
			Req[4] = 25;	//32 bytes - ipmb message header - response - checksum2
			wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pSession, PAYLOAD_TYPE_IPMI, 0x2e<<2, 0x83,
																	(uint8_t*)Req, 5,
																	(uint8_t *)Res, &dwResLen,
																	timeout);
			if((wRet != 0) || (Res[0] != 0))
			{
				printf("---> get Title error\n");
				return -1;
			}
			strLen = (Res[1]<<8) | Res[2];
			remainLen = (Res[3]<<8) | Res[4];
			
			memcpy(extraInfo->title + offset,&Res[5],strLen);
			offset += strLen;
		}while(remainLen > 0);
		
		//get text
		offset = 0;
		do{
			
			Req[0] = 1;
			Req[1] = (offset>>8)&0xff;
			Req[2] = offset&0xff;
			Req[3] = 0;	
			Req[4] = 20;	//32 bytes - ipmb message header - response header - checksum2
			wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pSession, PAYLOAD_TYPE_IPMI, 0x2e<<2, 0x83,
																	(uint8_t*)Req, 5,
																	(uint8_t *)Res, &dwResLen,
																	timeout);
			if((wRet != 0) || (Res[0] != 0))
			{
				printf("---> get Text error\n");
				return -1;
			}
			strLen = (Res[1]<<8) | Res[2];
			remainLen = (Res[3]<<8) | Res[4];
			
			memcpy(extraInfo->text + offset,&Res[5],strLen);
			offset += strLen;
		}while(remainLen > 0);
	}
	
	return 0;
}



LIBIPMI_API uint16_t
LIBIPMI_HL_GetSensorHistory( IPMI20_SESSION_T *pSession, sensor_history_st *pSensorHistory_st, int card_index, int sensor_number, int IPMB_ADDR)
{
	printf(">come in history\n");
	int i = 0;
	uint8_t	 	RawHistory[MAX_HISTORY_LEN];
	uint16_t    wRet;
	uint32_t    dwResLen;
	uint32_t	sdr_buff_size = 100;
	uint8_t 	Req[5];
	uint8_t 	Res[MAX_HISTORY_LEN+3];	
	int timeout = 3;
	FullSensorRec_T sdr_buffer;
	uint16_t 	offset = 0;
	uint16_t	reqLen = 0, resLen = 0;
	//get factors
	LIBIPMI_HL_GetSpecificSDR( pSession, (uint8_t*)&sdr_buffer, &sdr_buff_size, sensor_number, timeout );	
	
	//get history
	if( pSession->byMediumType == IPMB_MEDIUM )
	{
		reqLen = 22;	//32 bytes - ipmb message header - response header - checksum2
		do{
			Req[0] = sensor_number;
			Req[1] = (offset>>8)&0xff;
			Req[2] = offset&0xff;
			Req[3] = (reqLen>>8)&0xff;
			Req[4] = reqLen&0xff;
			wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pSession, PAYLOAD_TYPE_IPMI, 0x2e<<2, 0x89,
													(uint8_t*)Req, 5,
													(uint8_t *)Res, &dwResLen,
													timeout);
			if(wRet != 0)
			{
				return -1;
			}
			resLen = (Res[1]<<8) | Res[2];
			if(resLen > MAX_HISTORY_LEN)
			{
				printf("---> response length error: resLen = %#x\n", resLen);
				return -1;
			}
			memcpy(&RawHistory[offset],&Res[3],resLen);
			offset += resLen;
			if(offset >= MAX_HISTORY_LEN)	//get all history datas
			{
				reqLen = 0;
				break;
			}
			reqLen = ((MAX_HISTORY_LEN-offset)>22) ? 22 : (MAX_HISTORY_LEN-offset);		
		}while(reqLen);		
	}
	else
	{
		Req[0] = sensor_number;
		Req[1] = 0;
		Req[2] = 0;
		Req[3] = (MAX_HISTORY_LEN>>8)&0xff;
		Req[4] = MAX_HISTORY_LEN & 0xff;
		wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pSession, PAYLOAD_TYPE_IPMI, 0x2e<<2, 0x89,
														(uint8_t*)Req, 5,
														(uint8_t *)Res, &dwResLen,
														timeout);
		if(wRet != 0)
		{
			return -1;
		}
		
		resLen = (Res[1]<<8) | Res[2];
		if(resLen > MAX_HISTORY_LEN)
		{
			printf("---> response length error: resLen = %#x\n", resLen);
			return -1;
		}
		memcpy(RawHistory,&Res[3],resLen);
	}
	
	for(i=0;i < 480; i++)
	{
		ipmi_convert_reading( (uint8_t*)&sdr_buffer, RawHistory[i], (float*)&pSensorHistory_st->sensor_history[i] );
	}
	
	memset(pSensorHistory_st->sensor_name, 0,sizeof(pSensorHistory_st->sensor_name));
	memcpy(pSensorHistory_st->sensor_name, sdr_buffer.IDStr, sdr_buffer.IDStrTypeLen&0x3f);
	pSensorHistory_st->sensor_num = sensor_number;

	return 0;
}


uint16_t	LIBIPMI_HL_GetAllCards(IPMI20_SESSION_T *pSession,
		         CardStatus_T*	pResBladeSts,
					int timeout)
{
	uint16_t	wRet;
	uint32_t	dwResLen;
	uint8_t	  ReqData = g_OemWebFlags.bladeNum;
	
	dwResLen = sizeof(CardStatus_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pSession, PAYLOAD_TYPE_IPMI,
						0x2e<<2, 0x82,
						(uint8_t*)&ReqData, (uint32_t)1,
						(uint8_t*)pResBladeSts, &dwResLen,
						timeout);
	if( wRet != 0 )
		printf("Error getting Blade Status Info\n");
						
	return wRet;
}

/************************************************* new add **********************************************************************/
int LIBIPMI_HL_GetChassisInfo(IPMI20_SESSION_T *pSession, OemChassisInfo_T* pChassisInfo, int timeout)
{
	uint8_t pRes[10];
	int wRet = 0;
	uint32_t	dwResLen;
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pSession, PAYLOAD_TYPE_IPMI,
							0x2e<<2, 0x80,
							NULL, 0,
							(uint8_t*)pRes,  &dwResLen,
							timeout);
	if( wRet != 0 )
		printf("Error getting Blade Status Info\n");
		
	pChassisInfo->slotNum = pRes[1];
	pChassisInfo->supportChassisManageFn = pRes[2];
	pChassisInfo->chassisManageFnEnable = pRes[3];
	pChassisInfo->chMCIndex = pRes[4];
	return 0;
}

int LIBIPMI_HL_GetBladeStatus(IPMI20_SESSION_T *pSession, OemBladeStatus_T BladeStatus[], int timeout)
{
	int wRet = 0;
	uint32_t	dwResLen;
	uint8_t pRes[MAX_BLADE_NUM*sizeof(OemBladeStatus_T)+1];
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pSession, PAYLOAD_TYPE_IPMI,
							0x2e<<2, 0x81,
							NULL, 0,
							(uint8_t*)pRes,  &dwResLen,
							timeout);
	if( wRet != 0 )
			printf("Error getting Blade Status Info\n");
		
	memcpy(BladeStatus, pRes+1, g_OemWebFlags.bladeNum*sizeof(OemBladeStatus_T));
	return 0;
}

int LIBIPMI_HL_GetIPMCCapability(IPMI20_SESSION_T *pSession, uint8_t bladeIndex, OemIPMCCapability_T* pIPMCCapability, int timeout)
{
	int wRet = 0;
	uint32_t	dwResLen;
	uint8_t pRes[sizeof(OemIPMCCapability_T)+1];
	

	if(pSession->byMediumType == UDS_MEDIUM)
	{
		pRes[1] = 1;
		pRes[2] = 1;
		pRes[3] = 1;
		pRes[4] = 1;
		pRes[5] = 1;
		pRes[6] = 1;
		pRes[7] = 1;
	}
	else
	{
			wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pSession, PAYLOAD_TYPE_IPMI,
									0x2e<<2, 0x88,
									NULL, 0,
									(uint8_t*)pRes,  &dwResLen,
									timeout);
			if( wRet != 0 )
					printf("Error LIBIPMI_HL_GetIPMCCapability\n");
	}
	
	memcpy(pIPMCCapability, pRes+1, sizeof(OemIPMCCapability_T));
	
	return 0;
}

int LIBIPMI_HL_SetBladeManageFn(IPMI20_SESSION_T *pSession, uint8_t enable, int timeout)
{
	int wRet = 0;
	uint32_t	dwResLen;
	uint8_t pReq[10];
	uint8_t pRes[10];
	
	pReq[0] = enable;
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pSession, PAYLOAD_TYPE_IPMI,
							0x2e<<2, 0x8a,
							(uint8_t*)pReq,	(uint32_t)1,
							(uint8_t*)pRes,  &dwResLen,
							timeout);
	if( wRet != 0 )
			printf("Error LIBIPMI_HL_SetBladeManageFn\n");
		
	return 0;
}

int LIBIPMI_HL_GetManageWebName(IPMI20_SESSION_T *pSession, char* webName, int timeout)
{
	int wRet = 0;
	uint32_t	dwResLen;
	uint8_t pRes[20];
	
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pSession, PAYLOAD_TYPE_IPMI,
							0x2e<<2, 0x84,
							NULL,	0,
							(uint8_t*)pRes,  &dwResLen,
							timeout);
	if( wRet != 0 )
			printf("Error LIBIPMI_HL_SetBladeManageFn\n");
	
	memset(webName, 0, 16);
	memcpy(webName, pRes+1, 16);
	return 0;
}

int LIBIPMI_HL_GetFanInfo(IPMI20_SESSION_T *pSession, OemFanInfo_T* pFanInfo, int timeout)
{
	int wRet = 0;
	uint32_t	dwResLen;
	uint8_t pRes[10];
	
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pSession, PAYLOAD_TYPE_IPMI,
							0x2e<<2, 0x85,
							NULL,	0,
							(uint8_t*)pRes,  &dwResLen,
							timeout);
	if( wRet != 0 )
			printf("Error LIBIPMI_HL_SetBladeManageFn\n");
	
	pFanInfo->fanNum = pRes[1];
	return 0;
}

int LIBIPMI_HL_GetSensorHistoryCapability(IPMI20_SESSION_T *pSession, uint8_t sensorNum, SensorHistoryCapability_T* pSensorHistoryCapability, int timeout)
{
	int wRet = 0;
	uint32_t	dwResLen;
	uint8_t pRes[10];
	
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pSession, PAYLOAD_TYPE_IPMI,
							0x2e<<2, 0x88,
							(uint8_t*)&sensorNum,	1,
							(uint8_t*)pRes,  &dwResLen,
							timeout);
	if( wRet != 0 )
			printf("Error LIBIPMI_HL_GetSensorHistoryCapability\n");
	
	pSensorHistoryCapability->isSupportSensorHistory = pRes[1];
	pSensorHistoryCapability->SensorHistoryEnable	=	pRes[2];
	return 0;
}

//int LIBIPMI_HL_GetSensorHistoryEn(IPMI20_SESSION_T *pSession, uint8_t* SensorHistoryEnable, int timeout)
//{
// int wRet = 0;
// uint32_t dwResLen;
// uint8_t pRes[10];
// 
// wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pSession, PAYLOAD_TYPE_IPMI,
//       0x2e<<2, 0x8c,
//       NULL, 0,
//       (uint8_t*)pRes,  &dwResLen,
//       timeout);
// if( wRet != 0 )
//   printf("Error LIBIPMI_HL_GetSensorHistoryEn\n");
// 
// *SensorHistoryEnable = pRes[1];
// return 0;
//}

int LIBIPMI_HL_SetSensorHistoryEn(IPMI20_SESSION_T *pSession, uint8_t sensorNum, uint8_t SensorHistoryEnable, int timeout)
{
 int wRet = 0;
 uint32_t dwResLen;
 uint8_t pRes[10];
 uint8_t pReq[10];
 
 pReq[0] = sensorNum;
 pReq[1] = SensorHistoryEnable;
 wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pSession, PAYLOAD_TYPE_IPMI,
       0x2e<<2, 0x8d,
       (uint8_t*)pReq, 2,
       (uint8_t*)pRes,  &dwResLen,
       timeout);
 if( wRet != 0 )
   printf("Error LIBIPMI_HL_SetSensorHistoryEn\n");
 
 return 0;
}
