/**************************************************************
$Workfile:   elmcope.c  $
***************************************************************
**
** FIRMWARE, Copyright (C) 2000-2002
** Ikanos Communications, Fremont, CA
** All rights reserved. 
**
** The information and contents of this file are the
** proprietary information of Ikanos Communication and may not
** be disclosed or used without the formal written approval of
** Ikanos Communication
**
$Revision: 1.1 $
$Date: 2006/10/16 04:34:50 $
***************************************************************/


/**************************************************************

	This file contains functions for 
	ELM related Protocol Entitry specific to the CO:

	Entire contents of this file covered by VTU_O define
**************************************************************/

#ifdef	VTU_O

#include <stdio.h>
#include <string.h>

#include "ipos.h"
#include "appconfig.h"
#include "apperrCode.h"
#include "apposmacro.h"
#include "portmap.h"

#include "elmlocal.h"
#include "elmdeferred.h"
#include "elmapp.h"


/*  forward declarations  */

static int 	iposELMCOFileTransferCompleteResp( ipos_port_id pid, U8 uid, U16 status,
		iposelm_transfer_info *pTransferInfo, iposelm_event_log_info *pRcvdEventLog );

static int	iposRequestRemoteEventLogTransfer( ipos_elm_cmd_handler *pCmd );


static ipos_elm_co	   	iposELMCo[MAX_NUM_OF_PORTS];

int		iposelm_file_expiration_tick = IPOSELM_FILE_EXPIRATION_TICK;

ipos_elm_co *
iposELMIndxGetCo( int index )
{
	if(index>MAX_NUM_OF_PORTS-1||index<0)
	{
		printf("Failed to get the ELM object: index=%d \n", index);
		return	NULL;
	}

	return(&iposELMCo[index]);
}

ipos_elm_co *
iposELMGetCoPe(ipos_port_id	pid)
{

	int	lineNum;
	if(getLineNum(pid, &lineNum)!=IPOS_SUCCESS)
	{
//		printf("Failed to get the ELM object \n");
//		return	NULL;
	}

	if(lineNum>MAX_NUM_OF_PORTS)
	{
		printf("Failed to get the ELM object: LineNum=%d \n", lineNum);
		return	NULL;
	}

	lineNum=lineNum-1;
	return(&iposELMCo[lineNum]);
}

/* initialize the ELM CO iFftp */
/* because of the reversal of file transfer roles vis-a-vis RFM,
   this method is mostly borrowed from iposRFMCPEiFftpInit	*/

static int
iposELMCOiFftpInit( ipos_elm_co	*pCoPe )
{
	int	errCode=IPOS_SUCCESS;

	pCoPe->sid = 0;
	pCoPe->stateiFftp = IPOSELM_IFFTP_CO_IDLE;

	pCoPe->displayLevel=4;		/* modulo for report, 1: report every block */

	/* clear the counter	*/
	pCoPe->cntDataBlock=0;

	/* Get the expiration timer	*/
	errCode=iposCreateTmr(&(pCoPe->ptmrExp));

	return	IPOS_SUCCESS;
}

/* initialize the ELM CO	*/

int iposELMCOInit( void )
{
	int		 i, errCode, lineNum;
	ipos_elm_co	*pCoPe;

	for(i=0;i<MAX_NUM_OF_PORTS;i++)
	{
		pCoPe=iposELMIndxGetCo(i);

		/* PID init	*/
		lineNum=i+1;
		errCode=getBmePortId(lineNum, &(pCoPe->pid));
		
		/* initialize the cmd obj */
		errCode=iposELMCmdInit(&(pCoPe->cmdHandler), pCoPe->pid);
		if(errCode!=IPOS_SUCCESS)
		{
			printf("FATAL ERROR: Command object Initialization Failed! %d \n", errCode);
			return	errCode;
		}

		/* initialize the iFFTP obj	*/

		errCode=iposELMCOiFftpInit(pCoPe);
		if(errCode!=IPOS_SUCCESS)
		{
			printf("FATAL ERROR: iFFTP object Initialization Failed! %d \n", errCode);
			return	errCode;
		}
		pCoPe->pCbEventLogComplete = NULL;	 /* callback when event log received */
		pCoPe->pCbRemoteBMEReset = NULL;  /* callback when remote BME reported reset */

		pCoPe->stateXfer = IPOSELM_CO_XFER_IDLE;
	}

	return	IPOS_SUCCESS;
}

/* send the ACK		*/

static int
coSendAck( ipos_elm_co *pCoPe, U32 ack, void *par)
{

	U8	EocMsg[ MAX_MSG_SIZE ];
	int	errCode;
	U16 ACK1, ACK2;

    /*printf( "in coSendAck for port b%dp%d, ack for sequence %ld\n",
	     pCoPe->pid.bmeNum, pCoPe->pid.portNum, ack );*/
	ACK1=(U16) ack;
	ACK2=(U16) ack;
	/* generate the header	*/

	EocMsg[ IPOSELM_MSGHDR_PT ] = IPOSELM_PT;
	EocMsg[ IPOSELM_MSGHDR_MSGTYPE ] = IPOSELM_MSG_ACK;
	EocMsg[ IPOSELM_MSGHDR_MSGLEN ] = 0x8;

	/* ack1=ack2=seq	*/

	EocMsg[ IPOSELM_FILE_SID ] =pCoPe->sid;
	EocMsg[ IPOSELM_FILE_ACK1 ] =(U8) ((ACK1&0xff00)>>8);
	EocMsg[ IPOSELM_FILE_ACK1+1 ] =(U8) (ACK1&0xff);

	EocMsg[ IPOSELM_FILE_ACK2 ] =(U8) ((ACK1&0xff00)>>8);
	EocMsg[ IPOSELM_FILE_ACK2+1 ]=(U8) (ACK1&0xff);

	/* send the EOC msg	*/

	errCode= iposEocSendDataStream( pCoPe->pid, 0x08, EocMsg, 0, (U32) pCoPe, NULL ); 
	
	pCoPe->cntDataBlock++;
	if(pCoPe->displayLevel>0)
	{
		if((pCoPe->cntDataBlock % pCoPe->displayLevel) == 0)
		{
			/*printf("%d ", ACK1 );*/
			printf( "." );
		}
	}

	return	errCode;
}

/* File expiration handler	*/
/* for new, reset file transfer state to IDLE
   and call the Event Log Completion routine (if present)  */

static	void
coTmrExpired(U32 arg1, U32 arg2)
{
	ipos_elm_co		*pCoPe;
	ipos_elm_cmd_handler	*pCmd;

	pCoPe=(ipos_elm_co *) arg1;

	printf("CO ELM: File transfer connection error detected \n"); 

/* file transfer state = IDLE Ready for restart */

    	pCoPe->stateiFftp=IPOSELM_IFFTP_CO_IDLE;
	pCoPe->stateXfer = IPOSELM_CO_XFER_IDLE;

	if (pCoPe->pCbEventLogComplete != NULL)
	{
		pCmd = &(pCoPe->cmdHandler);
	  	(pCoPe->pCbEventLogComplete)( pCmd->pid, pCmd->uidResp, IPOS_ERROR, NULL );
	}
}

/* timeout mechanism	*/

static	int
coPetTimer(ipos_elm_co	*pCoPe)
{
	int	errCode=IPOS_SUCCESS;   

	/* start the expiration timer*/
	errCode=iposSetTmr(pCoPe->ptmrExp, iposelm_file_expiration_tick, coTmrExpired,
				(U32) pCoPe, (U32) 0);
	return	errCode;
}

/* rcv DataBlk		*/

int
iposELMCOiFftpHandler( ipos_elm_co *pCoPe, U8 *pEocMsg)
{
	int	errCode = IPOS_SUCCESS;
	U8	sid;
	U16	seq;
	U8	*pProg;

	/* check the state active?	*/

	if (pCoPe->stateiFftp == IPOSELM_IFFTP_CO_IDLE)
	{
		seq=( (U16)pEocMsg[IPOSELM_FILE_SEQ]<<8) |
		   ( ((U16)pEocMsg[IPOSELM_FILE_SEQ+1]) & 0x0ff); 
		printf( "iFftp state is idle in iposELMCOiFftpHandler, seq: %d\n", seq );
		return	IPOS_SUCCESS;	/* co pe not in the right state: ignore the packet */

	}

  /* special state created for ELM.  The CO requests the event log; the
     CPE responds by sending data blocks instead of a ACK_ACK packet.	*/

	else if (pCoPe->stateiFftp == IPOSELM_IFFTP_CO_REQSTD)
	{
		pCoPe->stateiFftp = IPOSELM_IFFTP_CO_ACTIVE;

	    /* change the state */

		iposELMCmdStateUpdate( &(pCoPe->cmdHandler), ELM_EVNT_RESP_RCVD );

	/* reset the timer	*/

		errCode=iposResetTmr(pCoPe->cmdHandler.ptmrRsnd);
		if(errCode!=IPOS_SUCCESS)
		{
			return IPOS_ERROR;
		}

		errCode = iposSemGive( pCoPe->cmdHandler.semCmd );
	}

	/* check msgType	*/

	if(pEocMsg[ IPOSELM_MSGHDR_MSGTYPE ] != IPOSELM_MSG_DATA_BLOCK)
	{
		return	IPOS_SUCCESS;			/* other packets received: ignored */
	}

	/* check the session id	*/

	sid = pEocMsg[ IPOSELM_FILE_SID ];
	if(sid != pCoPe->sid)	 		/* not for this session, ignore the packet */
	{
	    printf( "remote session ID %d does not match local session ID of %d\n",
		     sid, pCoPe->sid );
		return	IPOS_SUCCESS;
	}                                                                                 

    /*  save the block	*/

	seq=( (U16)pEocMsg[IPOSELM_FILE_SEQ]<<8) | ( ((U16) pEocMsg[IPOSELM_FILE_SEQ+1]) & 0x0ff); 

    /*printf( "sequence number: %d\n", seq );*/
	if(seq>=MAX_NUM_DATA_BLOCKS)
	{
		return	IPOS_ERROR;

	}
	
	/* clear the timer	*/

	errCode=coPetTimer( pCoPe );
	if(errCode!=IPOS_SUCCESS)
	{
		printf( "CO ELM: problem setting file transfer timer for b%dp%d\n",
			 pCoPe->pid.bmeNum, pCoPe->pid.portNum );
		return	errCode;
	}

	pProg=pCoPe->eventLogAddr + seq*IPOS_DATA_BLK_SIZE;
    /*printf( "would copy %d bytes to 0x%x\n", IPOS_DATA_BLK_SIZE, pProg );*/
	memcpy(pProg, pEocMsg+IPOSELM_FILE_DATA, IPOS_DATA_BLK_SIZE);
	/* send the Ack	*/
	coSendAck(pCoPe, (U32) seq, NULL);

	return	errCode;
}

static int
iposELMCOiFftpComplete(ipos_port_id	pid)
{
	
	ipos_elm_co	*pCoPe;
	int		 errCode = 0;

	pCoPe=iposELMGetCoPe(pid);

	/* stop the error detection timer	*/

	errCode=iposResetTmr(pCoPe->ptmrExp);
	if(errCode!=IPOS_SUCCESS)
	{
		printf("CO ELM: Failed to reset the timer \n");
	}

	/* change the state	*/
	pCoPe->stateiFftp=IPOSELM_IFFTP_CO_IDLE;
	return	errCode;

}

static int
iposELMCOBmeResetResp( ipos_port_id pid, U8 uid )
{
	ipos_elm_co			*pCoPe;
	int				 errCode;
	U8				 msgLen = 0;
	U8		 		 msgBuf[ MAX_MSG_SIZE ];
	iposelm_ctrl_hdr		 msgStruct;

	pCoPe = iposELMGetCoPe( pid );
	if (pCoPe == NULL)
	{
		return( IPOS_ERROR );
	}

	iposELMCmdSetCtrlHdr(
			&msgStruct,
			 IPOSELM_MSG_BME_WAS_RESET,
			 IPOSELM_ACK_ACK,		/* ack always positive, never NACK */
			 uid
	);

	msgLen = iposELMStruct2Msg( &msgStruct, IPOSELM_MSG_BME_WAS_RESET, &msgBuf[ 0 ] );

	errCode = iposELMSendMsg( pid, &msgBuf[ 0 ], msgLen );
	return( IPOS_SUCCESS );
}


/* CPE sent the CO a command packet - respond to it */

static int
iposELMCOEvntHandler(ipos_elm_co *pCoPe, U8 *pEocMsg)
{
	int	errCode;
	U8	msgType;
	U8	msgStruct[MAX_STRUCT_SIZE];

	/* decode the Eoc Msg	*/

	errCode=iposELMMsg2Struct(pEocMsg, msgStruct, &msgType);
	if( errCode!=IPOS_SUCCESS)
	{
		printf("Not a Valid EOC msg for ELM CO, error code: %d \n", errCode);
		return	errCode;
	}

	switch(msgType)
	{
	  case IPOSELM_MSG_FILE_TR_COMPLETE:
	    {
		U16				 elmErrorCode = IPOS_SUCCESS;
		U32				 localCheckSum;
		iposelm_xfer_complete_req	*pXferCompleteReq =
			(iposelm_xfer_complete_req *) &msgStruct[ 0 ];

		/*printf( "iposELMCOEvntHandler received IPOSELM_MSG_FILE_TR_COMPLETE\n" );
		printf( "CPE sent us %lu data blocks, %ld data bytes\n",
		         pXferCompleteReq->transferInfo.dataBlockSent,
		         pXferCompleteReq->transferInfo.byteSent
	        );*/
		localCheckSum = iposRFMGetCheckSum( pCoPe->eventLogAddr, pCoPe->fileInfo.size );
		/*printf( "File info that was saved, size: %ld, check sum: %ld\n",
			 pCoPe->fileInfo.size, pCoPe->fileInfo.checkSum );
		printf( "local check sum: %ld\n", localCheckSum );*/
		if (localCheckSum != pCoPe->fileInfo.checkSum)
		  elmErrorCode = ELM_ERROR_CKSUM;
		iposELMCOFileTransferCompleteResp( pCoPe->pid,
						   pXferCompleteReq->ctrlHdr.uid,
						   elmErrorCode,
						  &pXferCompleteReq->transferInfo,
						  &pCoPe->fileInfo
		);
		
		iposELMCOiFftpComplete(pCoPe->pid);
		pCoPe->stateXfer = IPOSELM_CO_XFER_IDLE;
	    }
	    break;

	  case IPOSELM_MSG_BME_WAS_RESET:
	    {
		iposelm_ctrl_hdr	*pCtrlHdr = (iposelm_ctrl_hdr *) &msgStruct[ 0 ];

		iposELMCOBmeResetResp( pCoPe->pid, pCtrlHdr->uid );

		if (pCoPe->pCbRemoteBMEReset != NULL)
		{
	  		(pCoPe->pCbRemoteBMEReset)(
			    pCoPe->pid, pCoPe->cmdHandler.uidResp, IPOS_SUCCESS, NULL
			);
		}
		else
		{
			iposelm_bme_crash_req	*pBmeResetReport =
				(iposelm_bme_crash_req *) &msgStruct[ 0 ];

			printf( "for port b%dp%d, remote BME was reset with error code %ld\n",
				 pCoPe->pid.bmeNum, pCoPe->pid.portNum,
				 pBmeResetReport->crashReport.bmeErrorCode
			);
		}
	    }
	    break;

	  default:
	    printf( "Unexpected message %d for ELM CO\n", msgType );
	    break;
	}

	return	IPOS_SUCCESS;
}

/* top level CO callback, called by appEocMsgParser */

void
iposELMCOEntry(ipos_port_id pid, U8 *pEocMsg)
{
	int errCode;
	int	msgClass;
	ipos_elm_co	*pCoPe;

	/*printf( "from port b%dp%d at %ld, received message with header %d %d %d %d\n",
		 pid.bmeNum, pid.portNum, iposTickGet(),
		*pEocMsg, *(pEocMsg + 1), *(pEocMsg + 2), *(pEocMsg + 3)
	);*/

    /* check the PT: if not ELM protocol, exit	*/

	if (pEocMsg[ IPOSELM_MSGHDR_PT ] != EOC_ELM_PROTOCOL)
	{
		printf("fatal error: Non-ELM msg passed to the ELM CO PE\n"); 
        	return;
	}

	pCoPe=iposELMGetCoPe(pid);
	msgClass=msgCheckElmClass(pEocMsg);	

    /*printf( "in iposELMCOEntry, message of class %d\n", msgClass );*/
	if(pCoPe==NULL)
	{
		printf("Fatal error: Invalid PID for the CO\n");
		return;

	}

	switch (msgClass)
	{
	  case IPOSELM_MSG_RESPONSE:
		/*printf( "Received MSG_RESPONSE in iposELMCOEntry\n" );*/
		errCode=iposELMCmdCoreResp(&(pCoPe->cmdHandler),pEocMsg);
		break;

	  case IPOSELM_MSG_COMMAND:
		/*printf( "Received MSG_COMMAND in iposELMCOEntry\n" );*/
		errCode=iposELMCOEvntHandler( pCoPe, pEocMsg );
		break;

	  case IPOSELM_MSG_FILE:
		/*printf( "Received MSG_FILE in iposELMCOEntry\n" );*/
		errCode = iposELMCOiFftpHandler( pCoPe, pEocMsg );
		break;
	}
}

#define IPOSELM_FILE_TRANSFER_TIMER_DELAY	3	/* a bit more than 1 second */

static int
iposRequestRemoteEventLogTransfer( ipos_elm_cmd_handler *pCmd )
{
	int				 errCode = IPOS_SUCCESS;
	U8				 uid;
	ipos_elm_co			*pCoPe;
	iposelm_xfer_event_log_req	 msgStruct;
	iposelm_select_event_log_resp	*pSelectEventLogResp =
		(iposelm_select_event_log_resp *) &(pCmd->respStruct );

	/*printf( "IPOSELM_MSG_GET_EVENT_LOG, BME: %d, port: %d\n",
		 pCmd->pid.bmeNum, pCmd->pid.portNum );
	printf( "IPOSELM_MSG_GET_EVENT_LOG, ack: %d, event log size: %ld\n",
		 pSelectEventLogResp->ctrlHdr.ack, pSelectEventLogResp->eventLogInfo.size );*/

	uid = pSelectEventLogResp->ctrlHdr.uid;
	iposELMCmdSetCtrlHdr( &(msgStruct.ctrlHdr),
			        IPOSELM_MSG_FILE_TRANSFER, IPOSELM_ACK_CMD,
				uid );
	msgStruct.sid = 2;					/* session ID of 2 for ELM */
	errCode = iposELMCmdCoreReq( pCmd, IPOSELM_MSG_FILE_TRANSFER,
		   (void *) &msgStruct, IPOSELM_FILE_TRANSFER_TIMER_DELAY, uid, NULL );

   /* now mark the iFftp state as requested (NOT active) */

	pCoPe = iposELMGetCoPe( pCmd->pid );
	if (pCoPe == NULL)
	{
		printf(
	   "No ELM CO object for port b%dp%d\n", pCmd->pid.bmeNum, pCmd->pid.portNum
		);
		return( IPOS_ERROR );
	}
	pCoPe->stateiFftp = IPOSELM_IFFTP_CO_REQSTD;
	pCoPe->sid = msgStruct.sid;
	pCoPe->stateXfer = IPOSELM_CO_REQ_XFER_START;

	return( errCode );
}

static int
iposELMCOFileTransferCompleteResp( ipos_port_id pid, U8 uid, U16 status, iposelm_transfer_info *pTransferInfo, iposelm_event_log_info *pRcvdEventLog )
{
	ipos_elm_co			*pCoPe;
	int				 errCode = IPOS_SUCCESS;
	U8				 msgLen = 0;
	U8		 		 msgBuf[ MAX_MSG_SIZE ];
	iposelm_xfer_complete_resp	 msgStruct;

	pCoPe = iposELMGetCoPe( pid );
	if (pCoPe == NULL)
	{
		return( IPOS_ERROR );
	}

	iposELMCmdSetCtrlHdr(
			&(msgStruct.ctrlHdr),
			 IPOSELM_MSG_FILE_TR_COMPLETE,
			 (status == IPOS_SUCCESS) ? IPOSELM_ACK_ACK : IPOSELM_ACK_NACK,
			 uid
	);
	msgStruct.transferInfo = *pTransferInfo;
	msgStruct.rcvdEventLog = *pRcvdEventLog;

	msgLen = iposELMStruct2Msg( &msgStruct, IPOSELM_MSG_FILE_TR_COMPLETE, &msgBuf[ 0 ] );
	errCode = iposELMSendMsg( pid, &msgBuf[ 0 ], msgLen );

    /*printf( "IPOSELM_MSG_GET_EVENT_LOG completed, checking callback\n" );*/
	if (pCoPe->pCbEventLogComplete != NULL)
	{
	  	(pCoPe->pCbEventLogComplete)(
	    pCoPe->cmdHandler.pid, pCoPe->cmdHandler.uidResp, status, pCoPe->eventLogAddr );
	}

	return( errCode );
}

int
iposELMCOGetEventLogResult( ipos_elm_cmd_handler *pCmd )
{
	iposelm_select_event_log_resp	*pSelectEventLogResp =
		(iposelm_select_event_log_resp *) &(pCmd->respStruct );
	if (pSelectEventLogResp->ctrlHdr.ack == IPOSELM_ACK_ACK &&
	    pSelectEventLogResp->eventLogInfo.size > 2)
	{
		ipos_elm_co	*pCoPe;

		pCoPe = iposELMGetCoPe( pCmd->pid );
		if (pCoPe == NULL)
		{
			printf(
	   "No ELM CO object for port b%dp%d\n", pCmd->pid.bmeNum, pCmd->pid.portNum
			);
			return( IPOS_ERROR );
		}

		if (pSelectEventLogResp->eventLogInfo.size > DEFAULT_EVENT_LOG_SIZE)
		{
			printf(
	   "CPE's event log size of %ld exceeds our maximum size of %ld\n",
	    pSelectEventLogResp->eventLogInfo.size, (long) DEFAULT_EVENT_LOG_SIZE
			);
			return( IPOS_ERROR );
		}
		else if (pCoPe->stateXfer != IPOSELM_CO_XFER_IDLE)
		{
			/*printf( "extra ACK received for GET_EVENT_LOG, ignored\n" );*/
			return( IPOS_SUCCESS );
		}

		pCoPe->fileInfo = pSelectEventLogResp->eventLogInfo;
	    /*printf( "ELM CO: event log info: %ld  %ld\n",
		     pCoPe->fileInfo.size, pCoPe->fileInfo.checkSum
	    );*/

		iposRequestRemoteEventLogTransfer( pCmd );
	}
	else {
		if (pSelectEventLogResp->eventLogInfo.size <= 2)
		{
			printf(
		    "\nEmpty event log on target CPE through port b%dp%d; no transfer was done\n",
				pCmd->pid.bmeNum, pCmd->pid.portNum
			);
		}
		else
		{
			printf(
		   "\nProblem with event log on CPE side through port b%dp%d, no transfer was done\n",
				pCmd->pid.bmeNum, pCmd->pid.portNum
			);
		}

		printf( PROMPT );
	}

	return( IPOS_SUCCESS );
}

/*********************************************************/

app_co_elm		coAppElm[MAX_NUM_OF_PORTS];	/* the co application object	*/

int	coELMAppInit( void )
{

	int i;
	int	errCode;
	ipos_port_id pid;
	app_co_elm	*pAppCo;
	ipos_elm_co	*pCoPe;

	/* inititialize the timers	*/
	errCode=iposTmrInit();
	if(errCode!=IPOS_SUCCESS)
	{
		printf("iposELM: Timer Initialization Failed \n");
		return	errCode;

	}

	/* initialize the elmco PE	*/
	
	errCode=iposELMCOInit();
	if(errCode!=IPOS_SUCCESS)
	{
		printf("iposELM: CO ELM Initialization Failed \n");
		return	errCode;

	}
	/* initialize the app object	*/
	for(i=0;i<MAX_NUM_OF_PORTS;i++)
	{
		pAppCo=&coAppElm[i];
		/* get the app object	*/
		errCode=getBmePortId(i+1, &pid);	/* even if portID is not valid, continue on init */
		
		pAppCo->pid=pid;
		
		/* get ELMCO object	*/
		pCoPe=iposELMGetCoPe(pid);
		pCoPe->eventLogAddr = NULL;
		pAppCo->pCoPe=pCoPe;

		/* current displayLevel is 1	*/
		pAppCo->displayLevel=1;
	}

	return	IPOS_SUCCESS;
}

int
iposSetCbRemoteBmeReset( ipos_port_id pid, U8 uid, iposELMCmdCb pCb )
{
	ipos_elm_co	*pCoPe;

	pCoPe=iposELMGetCoPe( pid );
	if(pCoPe==NULL)
	{
		return IPOS_ERROR;
	}

	pCoPe->pCbRemoteBMEReset = pCb;	 /* callback when remote BME reported reset */

	return( IPOS_SUCCESS );
}
#endif  /* VTU_O */
