#include <string.h>
#include "OemSMMCmds.h"
#include "com_BmcType.h"
#include "main.h"
#include "Storlead.h"
#include "SensorMonitor.h"
#include "Sensor.h"
#include "com_IPMI_SDRRecord.h"
#include "SDR.h"

int  Storlead_GetSysInfo(uint8_t* pReq, uint8_t ReqLen,  uint8_t* pRes)
{
	char Title[] = "CPU info";
	char Text[] = "CPU:Intel;Freq:1 GHZ;Memory:8 GB;Brief:This section test long string. Very very long string. long enough? not long";
	int len = 0,remainLen = 0;
	uint16_t offset = (pReq[1]<<8) | pReq[2];
	int totalLen = 0;
	char *pStr = NULL;
	int reqLen = (pReq[3]<<8) | pReq[4];
	
	switch(pReq[0])
	{
	case 0:	//get Title
		while(Title[totalLen])
		{
			totalLen++;
		}printf("title total len = %#x\n",totalLen);
		pStr = Title;
		break;
	case 1:
		while(Text[totalLen])
		{
			totalLen++;
		}
		printf("text total len = %#x\n", totalLen);
		pStr = Text;
		break;
	default:
		*pRes = CC_PARAM_OUT_OF_RANGE;
		return 1;
	}
	
	*pRes= CC_NORMAL;

	if(offset > totalLen)
	{
		printf("Invalid offset: %#x\n", offset);
		*pRes= CC_PARAM_OUT_OF_RANGE;
		return 1;
	}
	
	if(reqLen == 0)	
	{
		len = totalLen - offset;
	}
	else
	{
		len = (reqLen > (totalLen-offset)) ? (totalLen-offset) : reqLen;
	}
	
	remainLen = totalLen - offset - len;
	*(pRes+1) = (len>>8)&0xff;
	*(pRes+2) = len&0xff;
	*(pRes+3) = (remainLen>>8)&0xff;
	*(pRes+4) = remainLen&0xff;
	memcpy(pRes+5, pStr+offset, len);

	// int i;
	// printf("Example 80h: ");
	// for(i=0;i<5+len;i++)
	// 	printf("%#x ", pRes[i]);
	// printf("\n");

	return 5+len;	
}

int  Storlead_GetSensorInfo(uint8_t* pReq, uint8_t ReqLen,  uint8_t* pRes)
{
	printf("Storlead_GetSensorInfo\n" );

	StorleadGetSensorInfoRes_T *pGetSensorInfoRes = (StorleadGetSensorInfoRes_T *)pRes;
    uint8_t*   		pValidSensor = NULL;
    uint16_t       	SensorIndex = pReq[0];
    SensorInfo_T    pSensor ;
    SenInfo_T       SensorInfo;
    uint8_t 		SensorIsSigned = FALSE;
    uint16_t 		SensorReading = 0;
    SensorSharedMem_T*    pSMSharedMem;
    SDRRecHdr_T*     	  pSDRRec;
    FullSensorRec_T*      FullSDR;
    CompactSensorRec_T*   CompSDR;
    int i = 0;
    int             totalsize;

    /* Get the Sensor Shared Memory */
    pSMSharedMem = (SensorSharedMem_T*)&g_BMCInfo.SensorSharedMem;

    if(g_BMCInfo.SenConfig.ValidSensorCnt == 0)
    {
        pGetSensorInfoRes->CompletionCode = OEMCC_SENSOR_INFO_EMPTY;
        printf("ValidSensorCnt is 0\n");
        return 1;
    }

    if(SensorIndex >= g_BMCInfo.SenConfig.ValidSensorCnt)
    {
        pGetSensorInfoRes->CompletionCode = CC_PARAM_OUT_OF_RANGE;
        printf("Invalid SenosrIndex %d\n", SensorIndex);
        return 1;
    }

    //pValidSensor = (uint8_t*)(pAMIGetSensorInfoRes+1);
    // for(i = 0; i < g_BMCInfo.SenConfig.ValidSensorCnt; i++)
    // {
        //SensorIndex = g_BMCInfo.SenConfig.ValidSensorList[i];
        pSensor = pSMSharedMem->SensorInfo[SensorIndex];

        /*Copy the SDR Header*/
        memcpy(&pGetSensorInfoRes->SensorInfo.hdr,pSensor.SDRRec,sizeof(SDRRecHdr_T));

        pGetSensorInfoRes->SensorInfo.SensorNumber = pSensor.SensorNumber;
        pGetSensorInfoRes->SensorInfo.SensorTypeCode = pSensor.SensorTypeCode;
        pGetSensorInfoRes->SensorInfo.EventTypeCode = pSensor.EventTypeCode;

        pGetSensorInfoRes->SensorInfo.Units1 = pSensor.Units1;
        pGetSensorInfoRes->SensorInfo.Units2 = pSensor.Units2;
        pGetSensorInfoRes->SensorInfo.Units3 = pSensor.Units3;

        pGetSensorInfoRes->SensorInfo.M_LSB = pSensor.M_LSB;
        pGetSensorInfoRes->SensorInfo.M_MSB_Tolerance = pSensor.M_MSB_Tolerance;
        pGetSensorInfoRes->SensorInfo.B_LSB = pSensor.B_LSB;
        pGetSensorInfoRes->SensorInfo.B_MSB_Accuracy = pSensor.B_MSB_Accuracy;
        pGetSensorInfoRes->SensorInfo.Accuracy_MSB_Exp = pSensor.Accuracy_MSB_Exp;
        pGetSensorInfoRes->SensorInfo.RExp_BExp = pSensor.RExp_BExp;

        pGetSensorInfoRes->SensorInfo.LowerNonCritical = pSensor.LowerNonCritical;
        pGetSensorInfoRes->SensorInfo.LowerCritical = pSensor.LowerCritical;
        pGetSensorInfoRes->SensorInfo.LowerNonRecoverable = pSensor.LowerNonRecoverable;
        pGetSensorInfoRes->SensorInfo.UpperNonCritical = pSensor.UpperNonCritical;
        pGetSensorInfoRes->SensorInfo.UpperCritical = pSensor.UpperCritical;
        pGetSensorInfoRes->SensorInfo.UpperNonRecoverable= pSensor.UpperNonRecoverable;
        pGetSensorInfoRes->SensorInfo.Settable_Readable_ThreshMask= pSensor.SettableThreshMask;

        pGetSensorInfoRes->SensorInfo.Flags = pSensor.EventFlags & 0xe0;
        if((pSensor.EventFlags & BIT5) != 0)
        {
            pGetSensorInfoRes->SensorInfo.SensorReading = 0;
        }

        SensorReading = pSensor.SensorReading;
        pGetSensorInfoRes->SensorInfo.SensorReading = 0;
        SensorIsSigned = ( 0 != (pSensor.InternalFlags & BIT1));

        if (THRESHOLD_SENSOR_CLASS  == pSensor.EventTypeCode)
        {
            pGetSensorInfoRes->SensorInfo.SensorReading = (SensorReading & 0x00FF);
            pGetSensorInfoRes->SensorInfo.ComparisonStatus = 0;
            if((pSensor.DeassertionEventEnablesByte2 & BIT6) == BIT6 )
            {
                if (CompareValues(SensorIsSigned, pGetSensorInfoRes->SensorInfo.SensorReading, pSensor.UpperNonRecoverable) >= 0)
                {
                    pGetSensorInfoRes->SensorInfo.ComparisonStatus |= BIT5;
                }
            }
            if((pSensor.DeassertionEventEnablesByte2 & BIT5) == BIT5 )
            {
                if (CompareValues(SensorIsSigned, pGetSensorInfoRes->SensorInfo.SensorReading, pSensor.UpperCritical) >= 0)
                {
                    pGetSensorInfoRes->SensorInfo.ComparisonStatus |= BIT4;
                }
            }
            if((pSensor.DeassertionEventEnablesByte2 & BIT4) == BIT4 )
            {
                if (CompareValues(SensorIsSigned, pGetSensorInfoRes->SensorInfo.SensorReading, pSensor.UpperNonCritical) >= 0)
                {
                    pGetSensorInfoRes->SensorInfo.ComparisonStatus |= BIT3;
                }
            }
            if((pSensor.AssertionEventEnablesByte2 & BIT6) == BIT6 )
            {
                if (CompareValues(SensorIsSigned, pGetSensorInfoRes->SensorInfo.SensorReading, pSensor.LowerNonRecoverable) <= 0)
                {
                    pGetSensorInfoRes->SensorInfo.ComparisonStatus |= BIT2;
                }
            }
            if((pSensor.AssertionEventEnablesByte2 & BIT5) == BIT5 )
            {
                if (CompareValues(SensorIsSigned, pGetSensorInfoRes->SensorInfo.SensorReading, pSensor.LowerCritical) <= 0)
                {
                    pGetSensorInfoRes->SensorInfo.ComparisonStatus |= BIT1;
                }
            }
            if((pSensor.AssertionEventEnablesByte2 & BIT4) == BIT4 )
            {
                if (CompareValues(SensorIsSigned, pGetSensorInfoRes->SensorInfo.SensorReading, pSensor.LowerNonCritical) <= 0)
                {
                    pGetSensorInfoRes->SensorInfo.ComparisonStatus |= BIT0;
                }
            }

            pGetSensorInfoRes->SensorInfo.ComparisonStatus &= ((pSensor.SettableThreshMask >>  8) & 0xFF);
            pGetSensorInfoRes->SensorInfo.OptionalStatus = 0;
            // For Threshold sensor, [7:6] - reserved. Returned as 1b. Ignore on read.
            pGetSensorInfoRes->SensorInfo.ComparisonStatus |= THRESHOLD_RESERVED_BIT;
        }
        else
        {
            pGetSensorInfoRes->SensorInfo.ComparisonStatus = (((uint8_t) (SensorReading & 0x00FF)) & ((uint8_t) (pSensor.SettableThreshMask & 0x00FF)) );
            pGetSensorInfoRes->SensorInfo.OptionalStatus   = (((uint8_t) (SensorReading >> 8)) & ((uint8_t) (pSensor.SettableThreshMask >> 8)) );
            // For Discrete sensor, [7] - reserved. Returned as 1b. Ignore on read.
            pGetSensorInfoRes->SensorInfo.OptionalStatus  |= DISCRETE_RESERVED_BIT;
        }

        if((pSensor.EventFlags & BIT7) == 0)
        {
            pGetSensorInfoRes->SensorInfo.AssertionEventByte1 = 0;
            pGetSensorInfoRes->SensorInfo.AssertionEventByte2 = 0;
            pGetSensorInfoRes->SensorInfo.DeassertionEventByte1 = 0;
            pGetSensorInfoRes->SensorInfo.DeassertionEventByte2 = 0;
        }
        if((pSensor.SensorCaps & BIT6) == 0)
        {
             pGetSensorInfoRes->SensorInfo.AssertionEventByte1    = (pSensor.AssertionHistoryByte1 & pSensor.AssertionEventEnablesByte1);
             pGetSensorInfoRes->SensorInfo.AssertionEventByte2    = (pSensor.AssertionHistoryByte2 & pSensor.AssertionEventEnablesByte2);
             pGetSensorInfoRes->SensorInfo.DeassertionEventByte1    = (pSensor.DeassertionHistoryByte1 & pSensor.DeassertionEventEnablesByte1);
             pGetSensorInfoRes->SensorInfo.DeassertionEventByte2    = (pSensor.DeassertionHistoryByte2 & pSensor.DeassertionEventEnablesByte2);
        }
        else
        {
             pGetSensorInfoRes->SensorInfo.AssertionEventByte1    = (pSensor.AssertionEventOccuredByte1 & pSensor.AssertionEventEnablesByte1);
             pGetSensorInfoRes->SensorInfo.AssertionEventByte2    = (pSensor.AssertionEventOccuredByte2 & pSensor.AssertionEventEnablesByte2);
             pGetSensorInfoRes->SensorInfo.DeassertionEventByte1    = (pSensor.DeassertionEventOccuredByte1 & pSensor.DeassertionEventEnablesByte1);
             pGetSensorInfoRes->SensorInfo.DeassertionEventByte2    = (pSensor.DeassertionEventOccuredByte2 & pSensor.DeassertionEventEnablesByte2);
        }
        pSDRRec = GetSDRRec(pSensor.SDRRec->ID);
        if(pSensor.SDRRec->Type  == FULL_SDR_REC)       /*Full SDR*/
        {
            FullSDR = (FullSensorRec_T *)pSDRRec;
            pGetSensorInfoRes->SensorInfo.OwnerID = FullSDR->OwnerID;
            pGetSensorInfoRes->SensorInfo.OwnerLUN= FullSDR->OwnerLUN;
            pGetSensorInfoRes->SensorInfo.MaxReading = FullSDR->MaxReading;
            pGetSensorInfoRes->SensorInfo.MinReading = FullSDR->MinReading;
            pGetSensorInfoRes->SensorInfo.Linearization = FullSDR->Linearization;
            memset(pGetSensorInfoRes->SensorInfo.SensorName,0,MAX_ID_STR_LEN);
            strncpy(pGetSensorInfoRes->SensorInfo.SensorName,FullSDR->IDStr, MAX_ID_STR_LEN - (sizeof(FullSensorRec_T) - sizeof(SDRRecHdr_T) - FullSDR->hdr.Len));
        }
        else if(pSensor.SDRRec->Type == COMPACT_SDR_REC)   /*Compact SDR*/
        {
            CompSDR = (CompactSensorRec_T *)pSDRRec;
            pGetSensorInfoRes->SensorInfo.OwnerID = CompSDR->OwnerID;
            pGetSensorInfoRes->SensorInfo.OwnerLUN= CompSDR->OwnerLUN;
            pGetSensorInfoRes->SensorInfo.MaxReading = 0;
            pGetSensorInfoRes->SensorInfo.MinReading = 0;
            pGetSensorInfoRes->SensorInfo.Linearization = 0;
            memset(pGetSensorInfoRes->SensorInfo.SensorName,0,MAX_ID_STR_LEN);
            strncpy(pGetSensorInfoRes->SensorInfo.SensorName,CompSDR->IDStr, MAX_ID_STR_LEN - (sizeof(CompactSensorRec_T) - sizeof(SDRRecHdr_T) - CompSDR->hdr.Len));
        }
        //memcpy(pValidSensor,(uint8_t *)&SensorInfo,sizeof(SenInfo_T));
        //pValidSensor = pValidSensor + sizeof(SenInfo_T);
    //}

    pGetSensorInfoRes->CompletionCode = CC_NORMAL;
    //pAMIGetSensorInfoRes->Noofentries = g_BMCInfo.SenConfig.ValidSensorCnt;

    //totalsize = sizeof(AMIGetSensorInfoRes_T) + (sizeof(SenInfo_T) * 11/*g_BMCInfo.SenConfig.ValidSensorCnt*/);
    // printf("return %d :", totalsize);
    // for(i=0;i<sizeof(AMIGetSensorInfoRes_T) + (sizeof(SenInfo_T) * g_BMCInfo.SenConfig.ValidSensorCnt);i++)
    // 	printf("%#x ", pRes[i]);
    // printf("\n");

    return sizeof(StorleadGetSensorInfoRes_T);
}
