/**************************************************************
$Workfile:   rfmpe.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 $
***************************************************************/
#include	<stdio.h>
#include	<string.h>

#include	"appconfig.h"
#include 	"ipos.h"
#include	"rfmdef.h"
#include	"rfmerr.h"
#include	"ipostimer.h"

#include	"rfmstruct.h"
#include 	"rfmifco.h"
#include	"rfmifcpe.h"
#include	"rfmlocal.h"

#include 	"portmap.h"

	  
																

/*local function prototype	*/
						  
static	int		iposRFMSendMsg(ipos_port_id	pid, U8 msgLen, U8 *pMsg);
static	void	msgSendComplete(ipos_port_id	pid, U8 uid, U32 upar, int status, void *par);

static void	iposRFMCmdCoreResend(U32 arg1, U32 arg2);


/***************************************************************
		 send a EOC packet	
 ***************************************************************/
static	int	iposRFMSendMsg(ipos_port_id	pid, U8 msgLen, U8 *pMsg)
{
	
	return	iposEocSendDataStream(pid, msgLen+1, pMsg, 0, 0, msgSendComplete);   

}
						   

static	void	msgSendComplete(ipos_port_id	pid, U8 uid, U32 upar, int status, void *par)
{
	return;
}




/***************************************************************
		 core command/response handler for both CPE and CO	
 ***************************************************************/

int	iposRFMCmdInit(ipos_rfm_cmd_handler *pCmd, ipos_port_id pid)
{
	
	int	errCode=IPOS_SUCCESS;
	/* PID	*/
	pCmd->pid=pid;

	/* allocate the semphore	*/
	pCmd->semCmd=iposSemCreate();

	/* initial command state 	*/
	pCmd->stateCmd=IPOSRFM_STATE_CMD_IDLE;

	/* counters	*/
	pCmd->cntRsnd=0;

	/* Get the resend timer	*/
	errCode=iposCreateTmr(&(pCmd->ptmrRsnd));

	/* others	*/
	pCmd->resendTick=1;
	pCmd->msgLen=MAX_MSG_SIZE-1;
	pCmd->pCbCmd=NULL;

	return	errCode;

}
									 
int	iposRFMCmdCoreReq(ipos_rfm_cmd_handler *pCmd, int cmdType, void	*pMsgStruct, int resndTimes,
						U8	uPar, iposRFMCmdCb	pCbCmd)
{

	U8	msgLen;
	int errCode;


	/* take the semaphore: one command at a time	*/
	errCode=iposSemTake(pCmd->semCmd, IPOS_WAIT_FOREVER);
	if(errCode!=OS_SUCCESS)
	{
		return (IPOSRFM_ERROR_NOSEM);

	}

	/* setup callback	*/
	pCmd->uPar=uPar;
	pCmd->pCbCmd=pCbCmd;

	/* coding the command	*/
    msgLen=iposRFMStruct2Msg(pMsgStruct,cmdType, pCmd->msgRsn, &msgLen);  
	
	/* send the command		*/
	errCode=iposRFMSendMsg(pCmd->pid, msgLen, pCmd->msgRsn);
	if(errCode!=IPOS_SUCCESS)
	{
		return (IPOSRFM_ERROR_SENDMSG);

	}

	/* reset the resend counter	*/
	pCmd->cntRsnd=IPOSRFM_DATABLK_RESEND;		/* max number of resend: global defined	*/
	pCmd->resendTick=resndTimes;				/* num of ticks before resend	*/
	
	errCode=iposSetTmr(pCmd->ptmrRsnd,resndTimes,iposRFMCmdCoreResend,(U32) pCmd, (U32) 0);

	/* change the state		*/
	iposRFMCmdStateUpdate(pCmd, RFM_EVNT_CMD_SENT);

    
	/* set the timer		*/
	
	if(errCode!=IPOS_SUCCESS)
	{
		return (IPOSRFM_ERROR_TMR);

	}
	

#ifdef	TEST_CO

	sendToCpe(pCmd->pid, msgLen, pCmd->msgRsn);

#endif

#ifdef	TEST_CPE
	sendToCo(pCmd->pid, msgLen, pCmd->msgRsn);
#endif
	return	IPOS_SUCCESS;
}

						

int	iposRFMCmdCoreResp( ipos_rfm_cmd_handler *pCmd, U8 *pMsgRcved)
{

	U8	msgType, state;
	int	errCode;
	
	/* check the state:	repsond already received?	Skip	*/
	state=iposRFMCmdGetState(pCmd);
	if(state==IPOSRFM_STATE_CMD_IDLE)
	{
		return	IPOS_SUCCESS;

	}
	
	/* match the response with the command. No match? Skip */

	errCode=msgMatchCmdResp(pMsgRcved, pCmd->msgRsn);
	if(errCode!=IPOS_SUCCESS)
	{
		return	IPOSRFM_ERROR_UNKNOWN_MSG;
	}

	/* parse the message	*/
	
	errCode=iposRFMMsg2Struct(pMsgRcved, &(pCmd->respStruct), &msgType);
	if(errCode!=IPOS_SUCCESS)
	{
		return IPOSRFM_ERROR_MSGDECOING;

	}

	/* issues the internal iFFTP control function */

	switch(msgType)
	{
//#ifdef	PVTU_O
    case	 IPOSRFM_MSG_FILE_TRANSFER:
		if(pMsgRcved[IPOSRFM_MSGHDR_ACK]==IPOSRFM_ACK_ACK)		/* positive response	*/
		{
			errCode=iposRFMCOiFftpStart(pCmd->pid, 1);					/* session is 1 for now */
			if(errCode!=IPOS_SUCCESS)
			{
				return	errCode;
			}
		}

		break;


//#endif
//#ifdef	PVTU_R

//#endif
	default:
		break;
	}

	/* issue the external callback	*/

	if (pCmd->pCbCmd!=NULL) 
	{
		pCmd->pCbCmd(pCmd->pid, pCmd->uPar, IPOS_SUCCESS, (void *)pCmd-> respStruct);
	}
	
	/* change the state		*/

	iposRFMCmdStateUpdate(pCmd, RFM_EVNT_RESP_RCVD);

	/* reset the timer	*/
	errCode=iposResetTmr(pCmd->ptmrRsnd);
	if(errCode!=IPOS_SUCCESS)
	{
		return IPOSRFM_ERROR_TMR;
	}
	

   	/* give the semaphore	*/
	errCode=iposSemGive(pCmd->semCmd);
	if(errCode!=OS_SUCCESS)
	{
		return (IPOSRFM_ERROR_NOSEM);

	}

	return	IPOS_SUCCESS;

}
			 

#define	 db

static void	iposRFMCmdCoreResend(U32 arg1, U32 arg2)
{


	int	errCode;
	U8	msgLen;

	ipos_rfm_cmd_handler	*pCmd;

	pCmd=(ipos_rfm_cmd_handler *) arg1;

	msgLen=pCmd->msgLen;
	if(pCmd->cntRsnd>0)
	{

		pCmd->cntRsnd--;
		
        /* resend the command	*/
		errCode=iposRFMSendMsg(pCmd->pid, msgLen, pCmd->msgRsn);
#ifdef	db
		printf("resend\n");
#endif

		if(errCode!=IPOS_SUCCESS)
		{
			printf("RFM: cmd resend error \n");
			return;

		}
		
		/* set teh resend timer	*/
		errCode=iposSetTmr(pCmd->ptmrRsnd,pCmd->resendTick,iposRFMCmdCoreResend,(U32) pCmd, (U32) 0);
		if(errCode!=IPOS_SUCCESS)
		{
			printf("RFM: cmd resend timer error \n");
			return;


		}
		return;
	
	}
	else 		/* time out: callback with error */
	{
		/* issue the callback	*/
		if (pCmd->pCbCmd!=NULL) 
		{
			pCmd->pCbCmd(pCmd->pid, pCmd->uidResp, IPOSRFM_ERROR_TIMEOUT, (void *)pCmd->respStruct);
		}

		/* change the state		*/
		iposRFMCmdStateUpdate(pCmd, RFM_EVNT_RESP_EXPIRED);

		/* give the semaphore	*/
		errCode=iposSemGive(pCmd->semCmd);
		if(errCode!=OS_SUCCESS)
		{
			printf("RFM: sem give error \n");

		}

#ifdef	db
		printf("resend ends..\n");
#endif

		return;
	}

}
								

/****************************************************************************
	command/response state machine
	
****************************************************************************/
int		iposRFMCmdStateUpdate(ipos_rfm_cmd_handler *pCmd, int	Event)
{

	U8	curState;

	curState=pCmd->stateCmd;

	switch(curState)
	{

	case 	IPOSRFM_STATE_CMD_IDLE:

		if(Event==RFM_EVNT_CMD_SENT)
		{
			 pCmd->stateCmd=IPOSRFM_STATE_CMD_INPROGRESS;
		}

		break;

	case   IPOSRFM_STATE_CMD_INPROGRESS :

		if(Event==RFM_EVNT_RESP_RCVD||Event==RFM_EVNT_RESP_EXPIRED)
		{

			pCmd->stateCmd=IPOSRFM_STATE_CMD_IDLE;
		}

		break;

	default:

		break;
	}


	return	IPOS_SUCCESS;
}


int		iposRFMCmdGetState(ipos_rfm_cmd_handler *pCmd)
{

	return	pCmd->stateCmd;

}



	
/* message utilities shared between CPE and CO	*/
int	iposRFMCmdSetCtrlHdr(iposrfm_ctrl_hdr *pHdr, U8	msgType, U8 ackType, U8 uid) /* setup the control header	*/
{

	pHdr->genericHdr.pt=0x20;
	pHdr->genericHdr.msgType=msgType;
										/* length always filled by the parser	*/
	pHdr->uid=uid;
	pHdr->ack=ackType;

	return	IPOS_SUCCESS;
}


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

	Remote Firmware Management Entity CO side	(RFM_CO_PE)
	
	
**************************************************************/				

//#ifdef	VTU_O					

/* initialize the RFM CO	*/

int	iposRFMCOInit()
{
	int	i, errCode, lineNum;
	ipos_rfm_co	*pCoPe;

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

		pCoPe=iposRFMIndxGetCo(i);

		/* PID init	*/
		lineNum=i+1;
		errCode=getBmePortId(lineNum, &(pCoPe->pid));
		
		/* initialize the cmd obj */
		errCode=iposRFMCmdInit(&(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=iposRFMCOiFftpInit(pCoPe);
		if(errCode!=IPOS_SUCCESS)
		{
			printf("FATAL ERROR: iFFTP object Initialization Failed! %d \n", errCode);
			return	errCode;
		}

		/* Miscelenous Initialize	*/

		// ignore the errCode

		/* event callback init	*/

		pCoPe->pEvntError=NULL;
		pCoPe->pEvntFileSave=NULL;
		pCoPe->pEvntTransferComplete=NULL;

	}

	return	IPOS_SUCCESS;

}

int	iposRFMCOEvntHandler(ipos_rfm_co *pCoPe, U8  *pEocMsg)
{
	int	errCode;
	U8	msgType;
	U8	uid;	
	iposrfm_file_save_req  	*pFileSaveReqStruct ;
    
	U8	msgStruct[MAX_STRUCT_SIZE];

	/* decode the Eoc Msg	*/

	errCode=iposRFMMsg2Struct(pEocMsg, msgStruct, &msgType);

	if( errCode!=IPOS_SUCCESS)
	{
		printf("Not a Valid EOC msg: %d \n", errCode);
		return	errCode;
	}

	/* check the msgType	*/

	switch(msgType)
	{

	case	IPOSRFM_MSG_FILE_SAVE:

		pFileSaveReqStruct=(iposrfm_file_save_req *) msgStruct;
	   	uid=pFileSaveReqStruct->ctrlHdr.uid;
		if(pCoPe->pEvntFileSave!=NULL)
		{
			pCoPe->pEvntFileSave(pCoPe->pid, uid,pFileSaveReqStruct);

		}

		break;

	}
	/* handle the callback function with teh data structure	*/
	return	IPOS_SUCCESS;
    
}


/* entry point in the EOC APP for PT= 0x20	*/
void	iposRFMCOEntry(ipos_port_id pid, U8	*pEocMsg)
{
	int errCode;
	int	msgClass;
	ipos_rfm_co	*pCoPe;

    /* check the PT: if not 0x20, exit	*/
	if	(pEocMsg[IPOSRFM_MSGHDR_PT]!=0x20)
	{
		printf("fatal error: NonRFM msg passed to the CO_PE\n"); 
        	return;
	}


	pCoPe=iposRFMGetCoPe(pid);


	if(pCoPe==NULL)
	{

		printf("Fatal error: Invalid PID for the CO\n");
		return;

	}
	/* check msgClass			*/
	msgClass=MsgCheckClass(pEocMsg);	
	switch(msgClass)
	{

	case	IPOSRFM_MSG_RESPONSE:
		
		/* resp msg?  call the event handler  */
		errCode=iposRFMCmdCoreResp(&(pCoPe->cmdHandler),pEocMsg);
		if(errCode!=IPOS_SUCCESS)
		{
			printf("Wrong Response Received. \n");
		}

		/* update the ifftp state machine	*/
		errCode=iposRFMCOiFftpHandler(pCoPe, pEocMsg);
		if(errCode!=IPOS_SUCCESS)
		{
			printf("Wrong Response Received for iFFTP, errCoe = %i \n", errCode);
		}

		break;

	case 	IPOSRFM_MSG_COMMAND:
		/* cmd msg? call the event handler	*/
		errCode=iposRFMCOEvntHandler(pCoPe,pEocMsg);
		if(errCode!=IPOS_SUCCESS)
		{
			printf("Wrong Command Received. \n");
		}

        /* update the ifftp state machine	*/
	
		errCode=iposRFMCOiFftpHandler(pCoPe,pEocMsg);
	
		if(errCode!=IPOS_SUCCESS)
		{
			printf("Wrong Command Received for iFFTP, errCoe = %i \n", errCode);
		}

		break;
		
		
	case 	IPOSRFM_MSG_FILE:
		/* file ack? call the file ack handler	*/

		errCode=iposRFMCOiFftpHandler(pCoPe,pEocMsg);
	
		if(errCode!=IPOS_SUCCESS)
		{
			printf("Wrong Command Received for iFFTP, errCoe = %i \n", errCode);
		}

		break;

	 
	default:

		break;
	}


}


/* Cmd/Response	APIs	for CO	*/

int	iposRFMCOGetRemoteVersion(ipos_port_id pid, U8	uid, iposFuncRMVersion pComplete)
{
	int errCode;
	ipos_rfm_co	*pCoPe;
	ipos_rfm_cmd_handler	*pCmd;

	iposrfm_firmware_ver_req MsgStruct;

	pCoPe=iposRFMGetCoPe(pid);
	
	/* setup the structure	*/
	iposRFMCmdSetCtrlHdr(&(MsgStruct.ctrlHdr),IPOSRFM_MSG_FIRMWARE_VER,IPOSRFM_ACK_CMD, uid); /* setup the control header	*/
    
	/* setup the callback function	*/


	/* call Cmd Core functions			*/
	pCmd=&(pCoPe->cmdHandler);
	errCode=iposRFMCmdCoreReq(pCmd,IPOSRFM_MSG_FIRMWARE_VER, (void	*)&MsgStruct, 3,
							  uid, (iposRFMCmdCb)  pComplete);
	return	errCode;

}


int iposRFMCOActivateVersion(ipos_port_id pid, U8 uid, iposrfm_activation_info *pActInfo, 
   								iposFuncActivation pComplete)
{

	int errCode;
	ipos_rfm_co	*pCoPe;
	ipos_rfm_cmd_handler	*pCmd;

	iposrfm_activation_req MsgStruct;

	pCoPe=iposRFMGetCoPe(pid);
    
	/* setup the structure	*/
	iposRFMCmdSetCtrlHdr(&(MsgStruct.ctrlHdr),IPOSRFM_MSG_FIRMWARE_ACTIVATE,IPOSRFM_ACK_CMD, uid); /* setup the control header	*/
    
	memcpy(&(MsgStruct.activationInfo),pActInfo,sizeof(iposrfm_activation_info));

	/* call Cmd Core functions			*/
	
	pCmd=&(pCoPe->cmdHandler);
	errCode=iposRFMCmdCoreReq(pCmd,IPOSRFM_MSG_FIRMWARE_ACTIVATE, (void	*)&MsgStruct, 3,
							  uid, (iposRFMCmdCb)	pComplete);
	
	return	errCode;

}


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


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



int	iposRFMCOFileTransfer ( ipos_port_id pid, U8 uid, 
							
							iposrfm_file_info *pFileInfo, U8 *addr,	/* fileinfo and addr to be transfered */

							iposrfm_firmware_ver	*pVerBeReplaced, /* the proposed version to be replaced	*/
							
							iposFuncTransfer pComplete 				/* complete function */
							)
{


	int errCode;
	ipos_rfm_co	*pCoPe;
	ipos_rfm_cmd_handler	*pCmd;

	iposrfm_file_transfer_req MsgStruct;
	iposrfm_firmware_ver	any;
	U8	anystr[]="any\n";

	any.verId=0;
	any.lenStr=3;
	memcpy(&(any.verStr),anystr,3);

	pCoPe=iposRFMGetCoPe(pid);
    
	/* setup the structure	*/
	iposRFMCmdSetCtrlHdr(&(MsgStruct.ctrlHdr),IPOSRFM_MSG_FILE_TRANSFER,IPOSRFM_ACK_CMD, uid); /* setup the control header	*/
    
	memcpy(&(MsgStruct.newFileInfo),pFileInfo,sizeof(iposrfm_file_info));
	if(pVerBeReplaced==NULL)
	{
		pVerBeReplaced=&any;
	}
	memcpy(&(MsgStruct.firmwareReplaced),pVerBeReplaced,sizeof(iposrfm_firmware_ver));
	
	
	/* save the file address */
	pCoPe->firmwareAddr=addr;
	memcpy(&(pCoPe->fileInfo),pFileInfo,sizeof(iposrfm_file_info));
	/* call Cmd Core functions			*/
	pCmd=&(pCoPe->cmdHandler);
	errCode=iposRFMCmdCoreReq(pCmd,IPOSRFM_MSG_FILE_TRANSFER, (void	*)&MsgStruct, 3,
							  uid, (iposRFMCmdCb)	pComplete);
	
	return	errCode;


}



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


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

/* used internally by iFFTP    	*/
int	iposRFMCOiFftpComplete(ipos_port_id pid, U8 uid, iposrfm_transfer_info  *pInfo, iposFuncTrComplete pComplete)
{

	int errCode;
	ipos_rfm_co	*pCoPe;
	ipos_rfm_cmd_handler		*pCmd;
	iposrfm_transfer_complete_req	MsgStruct;


	pCoPe=iposRFMGetCoPe(pid);
    
	/* setup the structure	*/
	iposRFMCmdSetCtrlHdr(&(MsgStruct.ctrlHdr),IPOSRFM_MSG_FILE_TR_COMPLETE,IPOSRFM_ACK_CMD, uid); /* setup the control header	*/
	memcpy(&(MsgStruct.transferInfo),pInfo,sizeof(iposrfm_transfer_info));
	
	/* call Cmd Core functions			*/
	pCmd=&(pCoPe->cmdHandler);
	errCode=iposRFMCmdCoreReq(pCmd,IPOSRFM_MSG_FILE_TR_COMPLETE, (void	*)&MsgStruct, 3,
							  uid, (iposRFMCmdCb)	pComplete);
	
	return	errCode;

}



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


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


int	iposRFMCOTransferAbort( ipos_port_id pid, U8 uid, iposFuncCOAbort pComplete)
{

	return	IPOS_SUCCESS;
}

/* event/responding API	*/



int	iposRFMCORegFileSave(ipos_port_id pid,iposRFMCOEvntFileSave pHandler)
{

	ipos_rfm_co		*pCoPe;

	pCoPe=iposRFMGetCoPe(pid);

	if(pCoPe==NULL)
	{
		return IPOSRFM_ERROR_PID;

	}

	pCoPe->pEvntFileSave=pHandler;
	return	IPOS_SUCCESS;
}

/* respond to file save */
int	iposRFMCOFileSaveResp(ipos_port_id pid, U8 uid, U8 status)
{

	ipos_rfm_co		*pCoPe;
	int	errCode;
	U8	msgLen;
	iposrfm_file_save_resp MsgStruct;
	U8	msgBuf[MAX_MSG_SIZE];


	pCoPe=iposRFMGetCoPe(pid);
	if(pCoPe==NULL)
	{
		return IPOSRFM_ERROR_PID;

	}
    
	/* setup the structure	*/
	if(status==IPOS_SUCCESS)
	{
		iposRFMCmdSetCtrlHdr(&(MsgStruct.ctrlHdr),IPOSRFM_MSG_FILE_SAVE,IPOSRFM_ACK_ACK, uid); /* setup the control header	*/
	}
	else
	{
		iposRFMCmdSetCtrlHdr(&(MsgStruct.ctrlHdr),IPOSRFM_MSG_FILE_SAVE,IPOSRFM_ACK_NACK, uid); /* setup the control header	*/

	}
	/* coding the message	*/
	msgLen=iposRFMStruct2Msg(&MsgStruct, IPOSRFM_MSG_FILE_SAVE, msgBuf, &msgLen);
    
	/* send the message		*/
	errCode=iposRFMSendMsg(pid, msgLen, msgBuf);

#ifdef	TEST
	sendToCpe(pid, msgLen, msgBuf);
#endif	

	return	IPOS_SUCCESS;
}

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

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

int iposRFMCORegTransferComplete ( ipos_port_id pid, U8 uid, iposRFMCOEvntTransferComplete pHandler)
{

	ipos_rfm_co		*pCoPe;

	pCoPe=iposRFMGetCoPe(pid);

	if(pCoPe==NULL)
	{
		return IPOSRFM_ERROR_PID;

	}

	pCoPe->pEvntTransferComplete=pHandler;
	return	IPOS_SUCCESS;

}

/* respond to the complete req	*/
int	iposRFMCOTransferCompleteResp(ipos_port_id pid, U8 uid)
{

	return	IPOS_SUCCESS;
}

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


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

int	iposRFMCORegError(ipos_port_id pid, U8 uid, iposRFMCOEvntError pErrorHandler)
{
	ipos_rfm_co		*pCoPe;

	pCoPe=iposRFMGetCoPe(pid);

	if(pCoPe==NULL)
	{
		return IPOSRFM_ERROR_PID;

	}

	pCoPe->pEvntError=pErrorHandler;
	
	return	IPOS_SUCCESS;
}

//#endif


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

		functions specific for	CPE_PE
		
		
*********************************************************************************************/		 

//#ifdef	VTU_R
int	iposRFMCPEInit()
{
	int	i, errCode, lineNum;
	ipos_rfm_cpe	*pCpePe;

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

		pCpePe=iposRFMIndxGetCpe(i);

		/* PID init	*/
		lineNum=i+1;
		errCode=getBmePortId(lineNum, &(pCpePe->pid));
		// ignore the errCode

		/* initialize the cmd obj */
		errCode=iposRFMCmdInit(&(pCpePe->cmdHandler), pCpePe->pid );
		if(errCode!=IPOS_SUCCESS)
		{
			printf("FATAL ERROR: Command object Initialization Failed! %d \n", errCode);
			return	errCode;
		}

		/* initialize the iFFTP obj	*/
		errCode=iposRFMCPEiFftpInit(pCpePe);
		if(errCode!=IPOS_SUCCESS)
		{
			printf("FATAL ERROR: iFFTP object Initialization Failed! %d \n", errCode);
			return	errCode;
		}

		/* Miscelenous Initialize	*/

		/* event callback init	*/

		pCpePe->pEvntError=NULL;
		pCpePe->pEvntVersionReq=NULL;
		pCpePe->pEvntTransferReq=NULL;
		pCpePe->pEvntActivationReq=NULL;
		pCpePe->pEvntTransferCompleteReq=NULL;

	}

	return	IPOS_SUCCESS;

}

/* cpe event handler	*/
int	iposRFMCPEEvntHandler(ipos_rfm_cpe *pCpePe, U8 *pEocMsg)
{

	int	errCode;
	U8	msgType;
	U8	uid;	
	iposrfm_firmware_ver_req  	*pFwverReqStruct ;
	iposrfm_activation_req		*pActReqStruct ;
	iposrfm_file_transfer_req 	*pFileTrnReqStruct ;
	iposrfm_transfer_complete_req	  	*pFileTrnCompReqStruct ;
/*	iposrfm_transfer_abort_req	  		*pFileTrnAbortReqStruct ; */
    
	U8	msgStruct[MAX_STRUCT_SIZE];

	/* decode the Eoc Msg	*/

	errCode=iposRFMMsg2Struct(pEocMsg, msgStruct, &msgType);

	if( errCode!=IPOS_SUCCESS)
	{
		printf("Not a Valid EOC msg: %d \n", errCode);
		return	errCode;
	}

	/* check the msgType	*/

	switch(msgType)
	{

	case	IPOSRFM_MSG_FIRMWARE_VER:

		pFwverReqStruct=(iposrfm_firmware_ver_req *) msgStruct;
	   	uid=pFwverReqStruct->ctrlHdr.uid;
		if(pCpePe->pEvntVersionReq!=NULL)
		{
			pCpePe->pEvntVersionReq(pCpePe->pid, uid);

		}

		break;


	case	IPOSRFM_MSG_FIRMWARE_ACTIVATE:

		pActReqStruct=(iposrfm_activation_req *) msgStruct;
	   	uid=pActReqStruct->ctrlHdr.uid;
		if(pCpePe->pEvntActivationReq!=NULL)
		{
			pCpePe->pEvntActivationReq(pCpePe->pid, uid, &(pActReqStruct->activationInfo));

		}

		break;

	case	IPOSRFM_MSG_FILE_TRANSFER:

		pFileTrnReqStruct =(iposrfm_file_transfer_req *) msgStruct;
	   	uid=pFileTrnReqStruct->ctrlHdr.uid;
		
        memcpy(&(pCpePe->fileInfo), &(pFileTrnReqStruct->newFileInfo), sizeof(iposrfm_file_info));
		memcpy(&(pCpePe->firmwareReplaced),&(pFileTrnReqStruct->firmwareReplaced), sizeof(iposrfm_firmware_ver));

		if(pCpePe->pEvntTransferReq!=NULL)
		{
			pCpePe->pEvntTransferReq(pCpePe->pid, uid, &(pFileTrnReqStruct->newFileInfo),
									 &(pFileTrnReqStruct->firmwareReplaced));

		}

		break;

	case	IPOSRFM_MSG_FILE_TR_COMPLETE:

		/* reset the iFFTP state	*/
		iposRFMCPEiFftpComplete(pCpePe->pid);
	 


		pFileTrnCompReqStruct = (iposrfm_transfer_complete_req *) msgStruct;
		uid=pFileTrnCompReqStruct->ctrlHdr.uid;

		if(pCpePe->pEvntTransferCompleteReq!=NULL)
		{

			pCpePe->pEvntTransferCompleteReq(pCpePe->pid, uid, &(pFileTrnCompReqStruct->transferInfo));

		}


		break;


	}
	/* handle the callback function with teh data structure	*/
	return	IPOS_SUCCESS;

}



/* entry point in the EOC APP for PT= 0x20	*/
void	iposRFMCPEEntry(ipos_port_id pid, U8	*pEocMsg)
{

	int  errCode;
	int	msgClass;
	ipos_rfm_cpe	*pCpePe;

    /* check the PT: if not 0x20, exit	*/
	if	(pEocMsg[IPOSRFM_MSGHDR_PT]!=0x20)
	{
		printf("fatal error: NonRFM msg passed to the CPE_PE\n"); 
        	return;
	}


	pCpePe=iposRFMGetCpePe(pid);

#if 0
	if(errCode!=IPOS_SUCCESS)
	{

		printf("Fatal error: Invalid PID for the CPE\n");
		return;

	}
#endif
	/* check msgClass			*/
	msgClass=MsgCheckClass(pEocMsg);	
	switch(msgClass)
	{

	case	IPOSRFM_MSG_RESPONSE:
		
		/* resp msg?  call the event handler  */
		errCode=iposRFMCmdCoreResp(&(pCpePe->cmdHandler),pEocMsg);
		if(errCode!=IPOS_SUCCESS)
		{
			printf("Wrong Response Received. \n");
		}

		/* update the ifftp state machine	*/
		errCode=iposRFMCPEiFftpHandler(pCpePe, pEocMsg);
		if(errCode!=IPOS_SUCCESS)
		{
			printf("Wrong Response Received for iFFTP, errCoe = %i \n", errCode);
		}

		break;

	case 	IPOSRFM_MSG_COMMAND:
		/* cmd msg? call the event handler	*/
		errCode=iposRFMCPEEvntHandler(pCpePe,pEocMsg);
		if(errCode!=IPOS_SUCCESS)
		{
			printf("Wrong Command Received. \n");
		}

        /* update the ifftp state machine	*/
	
		errCode=iposRFMCPEiFftpHandler(pCpePe,pEocMsg);
	
		if(errCode!=IPOS_SUCCESS)
		{
			printf("Wrong Command Received for iFFTP, errCoe = %i \n", errCode);
		}

		break;
		
		
	case 	IPOSRFM_MSG_FILE:
		/* file ack? call the file ack handler	*/

		errCode=iposRFMCPEiFftpHandler(pCpePe,pEocMsg);
	
		if(errCode!=IPOS_SUCCESS)
		{
			printf("Wrong Command Received for iFFTP, errCoe = %i \n", errCode);
		}

		break;

	 
	default:

		break;
	}

}




/* command/response API for CPE	*/


int	iposRFMCPETransferAbort( ipos_port_id pid, U8 uid, iposFuncAbort pComplete)
{


	return	IPOS_SUCCESS;

}


int	iposRFMCPEFileSave(ipos_port_id pid, U8 uid, iposrfm_file_save_info *pFileSave,
					   iposFuncSave pComplete)
{

	int errCode;
	ipos_rfm_cpe	*pCpePe;
	ipos_rfm_cmd_handler	*pCmd;

	iposrfm_file_save_req MsgStruct;

	pCpePe=iposRFMGetCpePe(pid);
	
	/* setup the structure	*/
	iposRFMCmdSetCtrlHdr(&(MsgStruct.ctrlHdr),IPOSRFM_MSG_FILE_SAVE,IPOSRFM_ACK_CMD, uid); /* setup the control header	*/
		
	/* setup the callback function	*/
	memcpy(&(MsgStruct.fileSave),pFileSave,sizeof(iposrfm_file_save_info));

	/* call Cmd Core functions			*/
	pCmd=&(pCpePe->cmdHandler);
	errCode=iposRFMCmdCoreReq(pCmd,IPOSRFM_MSG_FILE_SAVE, (void	*)&MsgStruct, 3,
							  uid, (iposRFMCmdCb)  pComplete);
	return	errCode;

}


/* event/response for CPE	*/

int	iposRFMCPERegError(ipos_port_id pid, U8 uid, iposRFMCPEEvntError pErrorHandler)
{

		ipos_rfm_cpe	*pCpePe;
		pCpePe=iposRFMGetCpePe(pid);
		
		if(pCpePe==NULL)
		{
			return IPOSRFM_ERROR_PID;

		}

		pCpePe->uidEvntError=uid;
		pCpePe->pEvntError=pErrorHandler;

		return	IPOS_SUCCESS;

}


int	iposRFMCPERegVersionReq (ipos_port_id pid, iposRFMCPEEvntVersionReq pHandler)
{

	ipos_rfm_cpe	*pCpePe;
	
	pCpePe=iposRFMGetCpePe(pid);
	
	if(pCpePe==NULL)
	{
		return IPOSRFM_ERROR_PID;
	}

	pCpePe->pEvntVersionReq=pHandler;
	return	IPOS_SUCCESS;

}

/* respond to file version req  */
int iposRFMCPEVersionResp( ipos_port_id	pid, U8 uid, U8 status, iposrfm_ver_info *pRespInfo)
{

	ipos_rfm_cpe	*pCpePe;
	int	errCode;
	U8	msgLen;
	iposrfm_firmware_ver_resp MsgStruct;
	U8	msgBuf[MAX_MSG_SIZE];


	pCpePe=iposRFMGetCpePe(pid);
	if(pCpePe==NULL)
	{
		return IPOSRFM_ERROR_PID;

	}
	if(status==IPOS_SUCCESS)
	{	
	/* setup the structure	*/
		iposRFMCmdSetCtrlHdr(&(MsgStruct.ctrlHdr),IPOSRFM_MSG_FIRMWARE_VER,IPOSRFM_ACK_ACK, uid); /* setup the control header	*/
		memcpy(&(MsgStruct.verInfo),pRespInfo,sizeof(iposrfm_ver_info));
	}
	else
	{
		iposRFMCmdSetCtrlHdr(&(MsgStruct.ctrlHdr),IPOSRFM_MSG_FIRMWARE_VER,IPOSRFM_ACK_NACK, uid); /* setup the control header	*/
		memcpy(&(MsgStruct.verInfo),pRespInfo,sizeof(iposrfm_ver_info));
	}

	/* coding the message	*/
	msgLen=iposRFMStruct2Msg(&MsgStruct, IPOSRFM_MSG_FIRMWARE_VER, msgBuf, &msgLen);
    
	/* send the message		*/
	errCode=iposRFMSendMsg(pid, msgLen, msgBuf);

#ifdef	TEST
	sendToCo(pid, msgLen, msgBuf);
#endif	

	return	IPOS_SUCCESS;


}


int iposRFMCPERegTransferReq(ipos_port_id pid, iposRFMCPEEvntTransferReq pHandler)
{

	ipos_rfm_cpe	*pCpePe;

	pCpePe=iposRFMGetCpePe(pid);
	
	if(pCpePe==NULL)
	{
		return IPOSRFM_ERROR_PID;

	}

	pCpePe->pEvntTransferReq=pHandler;
	return	IPOS_SUCCESS;
}

/* respond to the file transfer request */
int	iposRFMCPETransferResp(ipos_port_id pid, U8 uid, U8 status, 
						   iposrfm_firmware_ver *pReplacedVersion,	/* replaced version confirmed by the App */
						   U8	*addr								/* the starting address to save the file */
						   )
{

	ipos_rfm_cpe	*pCpePe;
	int	errCode;
	U8	msgLen;
	
	iposrfm_file_transfer_resp MsgStruct;
	U8	msgBuf[MAX_MSG_SIZE];
	iposrfm_firmware_ver	any;
	U8	anystr[]="any\n";

	any.verId=0;
	any.lenStr=3;
	memcpy(&(any.verStr),anystr,3);

	if(pReplacedVersion==NULL)
	{
		pReplacedVersion=&any;
	}


	pCpePe=iposRFMGetCpePe(pid);
	if(pCpePe==NULL)
	{
		return IPOSRFM_ERROR_PID;

	}
	if(status==IPOS_SUCCESS)
	{	
	/* setup the structure	*/
		iposRFMCmdSetCtrlHdr(&(MsgStruct.ctrlHdr),IPOSRFM_MSG_FILE_TRANSFER,IPOSRFM_ACK_ACK, uid); /* setup the control header	*/
	/* setup the starting address	*/
		pCpePe->addrFirmware=addr;
	/* start CPE file receiving	*/
		iposRFMCPEiFftpStart(pid, 1, addr);
	
	}
	else
	{
		iposRFMCmdSetCtrlHdr(&(MsgStruct.ctrlHdr),IPOSRFM_MSG_FILE_TRANSFER,IPOSRFM_ACK_NACK, uid); /* setup the control header	*/
	}

	memcpy(&(MsgStruct.replacedFirmwareVer),pReplacedVersion,sizeof(iposrfm_firmware_ver));
	
	/* coding the message	*/
	msgLen=iposRFMStruct2Msg(&MsgStruct, IPOSRFM_MSG_FILE_TRANSFER, msgBuf, &msgLen);
    
	/* send the message		*/
	errCode=iposRFMSendMsg(pid, msgLen, msgBuf);

#ifdef	TEST
	sendToCo(pid, msgLen, msgBuf);
#endif	

	return	IPOS_SUCCESS;

}



int	iposRFMCPERegActivationReq(ipos_port_id pid,  iposRFMCPEEvntActivationReq pHandler)
{

	ipos_rfm_cpe	*pCpePe;

	pCpePe=iposRFMGetCpePe(pid);
	if(pCpePe==NULL)
	{
		return IPOSRFM_ERROR_PID;

	}

	pCpePe->pEvntActivationReq=pHandler;
	return	IPOS_SUCCESS;

}

/* respond to the activation request	*/
int	iposRFMCPEActivationResp(ipos_port_id pid, U8 uid, U8 status)
{

	ipos_rfm_cpe	*pCpePe;
	int	errCode;
	U8	msgLen;
	iposrfm_activation_resp MsgStruct;
	U8	msgBuf[MAX_MSG_SIZE];


	pCpePe=iposRFMGetCpePe(pid);
	if(pCpePe==NULL)
	{
		return IPOSRFM_ERROR_PID;

	}
    
	/* setup the structure	*/
	iposRFMCmdSetCtrlHdr(&(MsgStruct.ctrlHdr),IPOSRFM_MSG_FIRMWARE_ACTIVATE,IPOSRFM_ACK_ACK, uid); /* setup the control header	*/
    MsgStruct.activationStatus=status;

	/* coding the message	*/
	msgLen=iposRFMStruct2Msg(&MsgStruct, IPOSRFM_MSG_FIRMWARE_ACTIVATE, msgBuf, &msgLen);
    
	/* send the message		*/
	errCode=iposRFMSendMsg(pid, msgLen, msgBuf);

#ifdef	TEST
	sendToCo(pid, msgLen, msgBuf);
#endif	

	return	IPOS_SUCCESS;

}



int iposRFMCPERegTransferComplete ( ipos_port_id pid,  iposRFMCPEEvntTransferCompleteReq pHandler)
{

	ipos_rfm_cpe	*pCpePe;

	pCpePe=iposRFMGetCpePe(pid);
	if(pCpePe==NULL)
	{
		return IPOSRFM_ERROR_PID;

	}

	pCpePe->pEvntTransferCompleteReq=pHandler;
	return	IPOS_SUCCESS;
}

/* respond to the complete req	*/
int	iposRFMCPETransferCompleteResp(ipos_port_id pid, U8 uid, 
								   iposrfm_file_info	*pRcvedFileInfo)
{

	ipos_rfm_cpe	*pCpePe;
	int	errCode;
	U8	msgLen;
	iposrfm_transfer_complete_resp MsgStruct;
	U8	msgBuf[MAX_MSG_SIZE];


	pCpePe=iposRFMGetCpePe(pid);
	if(pCpePe==NULL)
	{
		return IPOSRFM_ERROR_PID;

	}
    
	/* setup the structure	*/
	
	iposRFMCmdSetCtrlHdr(&(MsgStruct.ctrlHdr),IPOSRFM_MSG_FILE_TR_COMPLETE,IPOSRFM_ACK_ACK, uid); /* setup the control header	*/
	MsgStruct.transferInfo.dataBlockSent=pCpePe->cntDataBlk;
	MsgStruct.transferInfo.byteSent=pCpePe->cntDataBlk*IPOS_DATA_BLK_SIZE;

	memcpy(&(MsgStruct.rcvedFile), pRcvedFileInfo, sizeof(iposrfm_file_info));


	/* coding the message	*/
	msgLen=iposRFMStruct2Msg(&MsgStruct, IPOSRFM_MSG_FILE_TR_COMPLETE, msgBuf, &msgLen);
    
	/* send the message		*/
	errCode=iposRFMSendMsg(pid, msgLen, msgBuf);

#ifdef	TEST
	sendToCo(pid, msgLen, msgBuf);
#endif	

	return	IPOS_SUCCESS;



}

//#endif								
