/*******************************************************************************
*
* File Name : atp_spp_apif.c
*
* Functions Handling the interface between ATP and SPP SW entity
*
* (C) Texas Instruments, all rights reserved
*
* Version number	: 0.1      Date : 16-Marsh-2000
*
* History			: 0.1  - Created by E. Baissus
*					  0.9 - Updated based on new SPP version and reviewed
*
* Author			: Eric Baissus : e-baissus@ti.com
*
*  (C) Copyright 2000 by Texas Instruments Incorporated, All Rights Reserved	
******************************************************************************/

#include "rv/rv_general.h"
#include "rvf/rvf_api.h"
#include "atp/atp_i.h"
#include "atp/atp_api.h"
#include "spp_general.h"
#include "atp/atp_config.h"
#include "atp/atp_spp_api.h"
#include "atp/atp_messages.h"
#include "spp_structs.h"
#include "spp_messages.h"
#include "spp_up_interface.h"
#include "atp/atp_spp_api_i.h"
#include "l2cap_data_hdlr.h" /* For L2CAP data handling */
#include "rvm/rvm_use_id_list.h"
#include <string.h>

/* Local variable */
static T_ATP_SW_ENTITY_ID atp_spp_sw_id;
static T_RVF_MB_ID spp_if_mb;
static T_RVF_ADDR_ID spp_addr_id = RVF_INVALID_ADDR_ID;
static T_ATP_SPP_PENDING_PORT_INFO pending_port_info[ATP_SPP_MAX_PENDING_PORT]; /* contains intermediate information during open port procedure */



/******************************************************************************
* Function name: atp_spp_from_spp_if_ft
*
* Description : Main function used to split the events coming from SPP
* and to forward to ATP
* 
*
* Parameters :  * message 
*
* Return     :   Standard error 
*				 RV_OK if  OK
*
* History			: 0.1 (17-Marsh-2000) 
*
******************************************************************************/
void atp_spp_from_spp_if_ft(void * message_p)
{
	
	T_RV_RET error;
	
	error = RV_OK;

	switch(((T_RV_HDR *)message_p)->msg_id)
	{
	case SPP_OPEN_PORT_CFM_EVT : 
		{	
			rvf_send_trace("ATP/SPP : Received a SPP_OPEN_PORT_CFM from SPP   ",50,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			
			error=atp_spp_open_port_rsp((void *) message_p,ATP_SPP_IS_CFM); 
			/* RV_OK or MEMORY ERROR or RV_NOT_SUPPORTED*/
			
			break;
		};
		
		
	case SPP_OPEN_PORT_IND_EVT : 
		{	
			rvf_send_trace("ATP/SPP : Received a SPP_OPEN_PORT_IND from SPP   ",50,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			
			error=atp_spp_open_port_rsp((void *) message_p,ATP_SPP_IS_IND); 
			/* RV_OK or RV_MEMORY_ERR or RV_NOT_SUPPORTED*/
			
			break;
		};
		
		
	case SPP_CLOSE_PORT_IND_EVT : 
		{
			
			rvf_send_trace("ATP/SPP : Received a SPP_CLOSE_PORT_IND from SPP   ",50,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			
			error=atp_close_port(atp_spp_sw_id,(T_ATP_PORT_NB) (((T_SPP_CLOSE_PORT_IND *) message_p)->handle)); 
			/* RV_OK or MEMORY ERROR or NOT_SUPPORTED*/

			/* Close server in case the port has been open is server mode */
			if (  ( ((T_SPP_CLOSE_PORT_IND *) message_p)->handle & SPP_HANDLE_TYPE) == SPP_SERVER_HANDLE_FLAG)
			{
				T_SPP_CLOSE_SERV * close_server_p;

				if (rvf_get_buf (spp_if_mb,sizeof(T_SPP_CLOSE_SERV),(void **) &close_server_p)==RVF_RED)
				{
					error = RV_MEMORY_ERR;
				}
				close_server_p->handle = ((T_ATP_CMD_RDY *) message_p)->port_nb;
				close_server_p->os_hdr.msg_id = SPP_CLOSE_SERV_EVT;
				
				rvf_send_trace("ATP/SPP : Send a SPP_CLOSE_SERV to SPP  ",40,
					NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
				
				rvf_send_msg (spp_addr_id,close_server_p);		
			}
			
			break;
		};
		
	case SPP_CLOSE_PORT_CFM_EVT : /* Acknowledge the port has been actually closed */
		{
			
			rvf_send_trace("ATP/SPP : Received a SPP_CLOSE_PORT_CFM from SPP   ",50,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID);
			
			/* Close server in case the port has been open is server mode */
			if (  ( ((T_ATP_PORT_CLOSED *) message_p)->port_nb & SPP_HANDLE_TYPE) == SPP_SERVER_HANDLE_FLAG)
			{
				
				T_SPP_CLOSE_SERV *	close_server_p;
				
				if (rvf_get_buf (spp_if_mb,sizeof(T_SPP_CLOSE_SERV),(void **) &close_server_p)==RVF_RED)
				{
					error = RV_MEMORY_ERR;
				}
				close_server_p->handle = ((T_SPP_CLOSE_PORT_CFM *) message_p)->handle;
				close_server_p->os_hdr.msg_id = SPP_CLOSE_SERV_EVT;
				
				rvf_send_trace("ATP/SPP : Send a SPP_CLOSE_SERV to SPP  ",40,
					NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
				
				rvf_send_msg (spp_addr_id,close_server_p);		
			}
			
			break;
		};

		

	case SPP_RECV_DATA_EVT : 
		{
			rvf_send_trace("ATP/SPP : Received a SPP_RECV_DATA_EVT from SPP   ",50,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			error=atp_no_copy_send_data(atp_spp_sw_id,
				(T_ATP_PORT_NB) ((T_SPP_RECV_DATA_NC *) message_p)->handle,
				(T_ATP_BUFFER)(((T_SPP_RECV_DATA_NC *) message_p)->l2cap_acl_data),
				((UINT32) ((T_SPP_RECV_DATA_NC *) message_p)->l2cap_acl_data->len));
			/* RV_OK or MEMORY ERROR */
			break;
		};
		
	case SPP_RETURN_MAX_PAYLOAD_EVT:
		{
			UINT16 * max_payload_p;

			rvf_send_trace("ATP/SPP : Received a SPP_RETURN_MAX_PAYLOAD_EVT from SPP ",57,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			rvf_send_trace("ATP/SPP : Send custom command ATP_FROM_SPP_MAX_PAYLOAD_IND_CMD to ATP ",70,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			
			if (rvf_get_buf (spp_if_mb,sizeof(UINT32),(void **) &max_payload_p)==RVF_RED)
			{
				error=RV_MEMORY_ERR;
			}
			else
			{
				*max_payload_p = ((T_SPP_RETURN_MAX_PAYLOAD *) message_p)->max_payload_length;
				error=atp_send_cmd(atp_spp_sw_id,
					(T_ATP_PORT_NB) ((T_SPP_RETURN_MAX_PAYLOAD *) message_p)->handle,
					CUSTOM_CMD,ATP_FROM_SPP_MAX_PAYLOAD_IND_CMD,max_payload_p);
			}
			break;
		}
		
		
	case SPP_RETURN_ERROR_EVT:
		{
			rvf_send_trace("ATP/SPP : Received a SPP_RETURN_ERROR_EVT from SPP ",51,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			rvf_send_trace("ATP/SPP : This event is not taken into account yet by ATP   ",60,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 			
			break;
		}
		
		
	case SPP_RETURN_MODEM_PARAM_EVT:
		{
			rvf_send_trace("ATP/SPP : Received a SPP_RETURN_MODEM_PARAM_EVT from SPP ",57,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			rvf_send_trace("ATP/SPP : This event is not taken into account yet by ATP   ",60,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			break;
		}
		
	case SPP_RETURN_LINE_STS_EVT:
		{
			rvf_send_trace("ATP/SPP : Received a SPP_RETURN_LINE_STS_EVT from SPP ",54,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			error=atp_spp_set_atp_signals(( T_SPP_LINE_STS *) message_p);			
			break;
		}
		
		
	default:
		{
			rvf_send_trace("ATP/SPP : A message received from ATP by ATP_SPP has been ignored ",66,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_HIGH, ATP_USE_ID); 
			break;
		};
	}
	
	/* Release SPP message buffer */
	rvf_free_buf(message_p);
	
	if (error != RV_OK)
	{
		rvf_send_trace("ATP/SPP : An error has been encountered when processing a message from SPP ",75,
			NULL_PARAM,RV_TRACE_LEVEL_WARNING, ATP_USE_ID); 
	}
	
}




/******************************************************************************
* Function name: atp_spp_to_spp_if_ft
*
* Description : Main function used to split the events coming from ATP
* and forwarded to SPP
* 
*
* Parameters :  * message 
*
* Return     :   Standard error 
*				 RV_OK if  OK
*
* History			: 0.1 (17-Marsh-2000) 
*
******************************************************************************/
void atp_spp_to_spp_if_ft( void * message_p)
{

	T_RV_RET error;

	error = RV_OK;

	
	switch(((T_ATP_MESSAGE *) message_p)->msg_id)
	{
	case ATP_OPEN_PORT_IND : 
		{
			rvf_send_trace("ATP/SPP : Received a ATP_OPEN_PORT_IND from ATP   ",50,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 


			error=atp_spp_open_port_rqst((T_ATP_OPEN_PORT_IND *) message_p); 
			/* RV_OK or MEMORY ERROR */
			
			break;
		};
		
		
	case ATP_PORT_CLOSED : 
		{
			rvf_send_trace("ATP/SPP : Received a ATP_PORT_CLOSED  from ATP    ",50,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			
			error=atp_spp_port_closed_from_atp((T_ATP_PORT_CLOSED *) message_p); 
		
			break;
		};
		
	case ATP_CMD_RDY : 
		{
			
			rvf_send_trace("ATP/SPP : Received a ATP_CMD_RDY  from ATP    ",50,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			
			rvf_send_trace("ATP/SPP : Command has been ignored ",35,
				NULL_PARAM,RV_TRACE_LEVEL_WARNING, ATP_USE_ID); 
			break;
		};
		
	case ATP_SIGNAL_CHANGED : 
		{
			error = atp_spp_set_spp_signals ((T_ATP_SIGNAL_CHANGED *) message_p);		
			break;
		};
		
		
		
	case ATP_ERROR : 
		{
			rvf_send_trace("ATP/SPP : Received a ATP_ERROR  from ATP ",41,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			rvf_send_trace("ATP/SPP : This event is not taken into account yet by ATP   ",60,
				NULL_PARAM,RV_TRACE_LEVEL_WARNING, ATP_USE_ID); 						
			break;
		};
		
	case ATP_NO_COPY_DATA_RDY : 
		{
			rvf_send_trace("ATP/SPP : Received a ATP_NO_COPY_DATA_RDY from ATP",50,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			
			error=atp_spp_send_to_spp_buffer_nc((T_ATP_NO_COPY_DATA_RDY *) message_p); 
			
			/* RV_OK or MEMORY ERROR */
			
			break;
		};
		
	default:
		{
			rvf_send_trace("ATP/SPP : A message received from ATP by ATP_SPP has been ignored ",66,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_HIGH, ATP_USE_ID); 
			break;
		};
	}
	
	/* Release ATP message buffer */
	atp_free_message(message_p);
	
	if (error != RV_OK)
	{
		rvf_send_trace("ATP/SPP : An error has been encountered when processing a message from ATP ",75,
			NULL_PARAM,RV_TRACE_LEVEL_WARNING, ATP_USE_ID); 
	}
		
}





/*********************************************************************************
*	
*	Function name: atp_spp_reg
*
*	Description: Used to register spp to ATP 
*
*	Parameters: None 
*
*	Return:  
*
*	History: 0.1 (11-Aug-2000) 
*
*********************************************************************************/
T_RV_RET atp_spp_reg(void)
{
	T_ATP_ENTITY_MODE mode;
	T_ATP_SW_ENTITY_NAME name;
	T_ATP_CALLBACK return_path;

	/* Register SPP to ATP */
	strcpy((char *) name,ATP_SPP_NAME);
	return_path.callback_func = atp_spp_to_spp_if_ft;
	mode.cmd_mode=INTERPRETED_MODE; /* Do not care : DCE EMU is ON */
	mode.cp_mode=COPY_OFF;
	mode.cmd_support_mode=CMD_SUPPORT_OFF; // SPP does not support command....only data
	
	if(atp_reg(name,return_path,mode,&atp_spp_sw_id)!=RV_OK)
	{
		rvf_send_trace("ATP_SPP: SPP entity registration failed ",39, NULL_PARAM ,
			RV_TRACE_LEVEL_WARNING,ATP_USE_ID); 
		return RV_INTERNAL_ERR;	
	}
	return RV_OK;
}


/******************************************************************************
* Function name: atp_spp_init
*
* Description : This function is called to initialise SPP with ATP
* 
*
* Parameters :  None
*
* Return     :   Standard error 
*				RV_OK if  OK
*
* History			: 0.1 (17-Marsh-2000) 
*
******************************************************************************/
T_RV_RET atp_spp_init(T_RVF_ADDR_ID addr_id, T_RVF_MB_ID mb_id)
{
	UINT8 i;

	/* Initialisation */
	spp_addr_id=addr_id; /* Mail box and task number to send primitive to SPP */
	spp_if_mb=mb_id;	/* Use SPP PRIM MB as working mb */

	for(i=0;i<ATP_SPP_MAX_PENDING_PORT;i++)
	{
		pending_port_info[i].port_nb=0;
		pending_port_info[i].initiator_id=ATP_INVALID_SWE_ID; /* Indicates that the field is free */
		pending_port_info[i].handle=0;
	}

	return RV_OK;
}



/******************************************************************************
* Function name: atp_spp_start
*
* Description : This function is called to register SPP to ATP
* 
*
* Parameters :  None
*
* Return     :   Standard error 
*				RV_OK if  OK
*
* History			: 0.1 (29-Oct-2001) 
*
******************************************************************************/
T_RV_RET atp_spp_start(void)
{
	if (atp_spp_reg() != RV_OK)
	{
		ATP_SEND_TRACE("ATP: Normal warning if ATP should not be started along with SPP",
			RV_TRACE_LEVEL_WARNING);
	}
	return RV_OK;
}




/******************************************************************************
* Function name: atp_spp_open_port_rqst
*
* Description : Translate ATP_OPEN_PORT_IND into SPP_OPEN_PORT_RQST
* 
*
* Parameters :  Message pointer
*
* Return     :   Standard error 
*				RV_OK if  OK
*
* History			: 0.1 (20-Marsh-2000) 
*
******************************************************************************/
T_RV_RET atp_spp_open_port_rqst(T_ATP_OPEN_PORT_IND * open_port_ind_p)
{	

	T_SPP_OPEN_PORT_RQST * spp_open_port_rqst_p;
	T_ATP_CUSTOM_TO_SPP_INFO * spp_custom_info_p;
	UINT8 i,j;
	
	if (open_port_ind_p->custom_info_p == NULL)
	{
		rvf_send_trace("ATP_SPP: Received an open port request from ATP without SPP information ",72, NULL_PARAM ,
			RV_TRACE_LEVEL_WARNING,ATP_USE_ID); 
		rvf_send_trace("ATP_SPP: =>  the ATP open port request has been ignored ",56, NULL_PARAM ,
			RV_TRACE_LEVEL_WARNING,ATP_USE_ID); 
		return RV_NOT_SUPPORTED;	
	}
	
	if (rvf_get_buf (spp_if_mb,sizeof(T_SPP_OPEN_PORT_RQST),(void **) &spp_open_port_rqst_p)!=RVF_RED)
	{
		
	/* Find an empty field in the pending_port_info array 
		and store intermediate value before getting a CFM or IND */
		i=0;
		while((pending_port_info[i].initiator_id!=ATP_INVALID_SWE_ID) &&
			(i<ATP_SPP_MAX_PENDING_PORT))
		{
			i++;
		}
		if (i==ATP_SPP_MAX_PENDING_PORT)
		{
			rvf_send_trace("ATP/SPP : Cannot open a new port : max authorized reached",57,
				NULL_PARAM,RV_TRACE_LEVEL_WARNING, ATP_USE_ID); 
			// SHOULD SEND A IGNORE MESSAGE TO ATP 
			rvf_free_buf(spp_open_port_rqst_p);
			return RV_NOT_SUPPORTED; 
			
		}
		pending_port_info[i].port_nb=open_port_ind_p->initiator_port_nb;
		pending_port_info[i].initiator_id=open_port_ind_p->initiator_id; 
		/* pending_port_info[i].handle address is provided later on to SPP for update */
		
		spp_custom_info_p = (T_ATP_CUSTOM_TO_SPP_INFO *) open_port_ind_p->custom_info_p;
		
		/* Update field for SPP event */
		spp_open_port_rqst_p->appli_rx_mb = spp_custom_info_p->rx_mb;
		if (spp_custom_info_p->max_payload_length_reneg_en == ATP_PAYLOAD_LENGTH_RENEG_ON)
		{
			spp_open_port_rqst_p->max_payload_reneg= SPP_ENABLE_MAX_PAYLOAD_RENEG;
		}
		else
		{
			spp_open_port_rqst_p->max_payload_reneg= SPP_DISABLE_MAX_PAYLOAD_RENEG;
		}
		spp_open_port_rqst_p->max_payload_length = spp_custom_info_p->max_payload_length;
		if (spp_custom_info_p->is_server==ATP_IS_SERVER)
		{
			spp_open_port_rqst_p->server_mode=SPP_SERVER;
		}
		else
		{
			spp_open_port_rqst_p->server_mode=SPP_CLIENT;
		}	
		
		if (spp_custom_info_p->flow_ctrl_mode==ATP_AUTOMATIC_FLOW_CTRL_OFF)
		{
			spp_open_port_rqst_p->rx_flow_ctrl=SPP_MANUAL_FLOW_CTRL;
		}
		else
		{
			spp_open_port_rqst_p->rx_flow_ctrl=SPP_AUTOMATIC_FLOW_CTRL;
		}	
		spp_open_port_rqst_p->serv_channel = (T_SERVER_CHANNEL) spp_custom_info_p->server_channel;
		spp_open_port_rqst_p->os_hdr.callback_func = atp_spp_from_spp_if_ft;
		spp_open_port_rqst_p->os_hdr.dest_addr_id = RVF_INVALID_ADDR_ID;
		for (j=0 ; j<sizeof(T_BD_ADDR) ; j++)
		{spp_open_port_rqst_p->bd_addr[j] = spp_custom_info_p->bd_addr[j];	}
		
		spp_open_port_rqst_p->modem_accept = AUTO_ACCEPT;
			
		spp_open_port_rqst_p->handle=&(pending_port_info[i].handle);
		spp_open_port_rqst_p->os_hdr.msg_id = SPP_OPEN_PORT_RQST_EVT;
		
		/* Free the custom info buffer */
		rvf_free_buf(spp_custom_info_p);
		
		rvf_send_msg (spp_addr_id,spp_open_port_rqst_p);		
		return (RV_OK);
	}
	else 
	{
		return(RV_MEMORY_ERR);
	}
}




/******************************************************************************
* Function name: atp_spp_open_port_rsp
*
* Description : Translate SPP_OPEN_PORT_CFM and IND to atp_open_port_rsp
* 
*
* Parameters :  Message pointer
*
* Return     :   Standard error 
*				RV_OK if  OK
*
* History			: 0.1 (20-Marsh-2000) 
*
******************************************************************************/
T_RV_RET atp_spp_open_port_rsp(void * spp_open_port_rsp_p,T_ATP_SPP_IS_IND_OR_CFM cfm_or_ind)
{
	T_ATP_OPEN_PORT_RESULT result;
	T_ATP_PORT_INFO port_info;
	T_ATP_NO_COPY_INFO no_copy_info;
	UINT8 i;
	T_RV_RET return_status;
	T_SPP_HANDLE handle;
	T_ATP_CUSTOM_FROM_SPP_INFO * custom_info_p;
	

	
	if (rvf_get_buf (spp_if_mb,sizeof(T_ATP_CUSTOM_FROM_SPP_INFO),(void **) &custom_info_p)==RVF_RED)
	{
		return RV_MEMORY_ERR;
	}

	if (cfm_or_ind==ATP_SPP_IS_CFM)
	{
		/* Result translation */
		if (((T_SPP_OPEN_PORT_CFM *) spp_open_port_rsp_p)->result!=SPP_OPEN_PORT_SUCCESS)
		{
			result=OPEN_PORT_NOK;
		}
		else
		{
			result=OPEN_PORT_OK;
		}
		handle=((T_SPP_OPEN_PORT_CFM *) spp_open_port_rsp_p)->handle;
		custom_info_p->max_payload_length = ((T_SPP_OPEN_PORT_CFM *) spp_open_port_rsp_p)->max_payload_length;
		memcpy(custom_info_p->bd_addr,"000000",BD_ADDR_LEN);
	}
	else
	{
		result=OPEN_PORT_OK;
		handle=((T_SPP_OPEN_PORT_IND *) spp_open_port_rsp_p)->handle;
		custom_info_p->max_payload_length = ((T_SPP_OPEN_PORT_IND *) spp_open_port_rsp_p)->max_payload_length;
		memcpy(custom_info_p->bd_addr,((T_SPP_OPEN_PORT_IND *) spp_open_port_rsp_p)->bd_addr,BD_ADDR_LEN);
		
		/* Create custom info field and update values */
	}
	
	custom_info_p->custom_type=ATP_FROM_SPP_INFO;
	
	/* Get field from pending_port_info */ 
	i=0;
	while(  ((pending_port_info[i].handle!=handle) || 
		(pending_port_info[i].initiator_id==ATP_INVALID_SWE_ID))       &&
		(i<ATP_SPP_MAX_PENDING_PORT))
	{
		i++;
	}
	if (i==ATP_SPP_MAX_PENDING_PORT)
	{
		rvf_send_trace("ATP/SPP : Port handle from SPP not found ",57,
			NULL_PARAM,RV_TRACE_LEVEL_WARNING, ATP_USE_ID);
		if (cfm_or_ind==ATP_SPP_IS_IND)
		{
			rvf_send_trace("ATP/SPP : SPP may have send a PORT_IND whereas no port has been created first as a server ",90,
			NULL_PARAM,RV_TRACE_LEVEL_WARNING, ATP_USE_ID);
		}	
		rvf_free_buf(custom_info_p);
		return RV_NOT_SUPPORTED; /* Ignore command */
	}
	
	/* Port info */
	port_info.port_config = NOT_DEFINED_CONFIG;
	port_info.dce_mask[0]=0x0000; /* Command to interpret by ATP are not fixed on SPP side */
	port_info.ring_type=ATP_NO_RING_TYPE;
	port_info.signal_mask=ATP_ALL_THE_SIGNAL_UNMASK; /* Get all the signals */
	
	/* No copy info */
	no_copy_info.packet_mode=SEGMENTED_PACKET;
	no_copy_info.tx_head_mode=TX_HEADER_ON;/* Do not care */
	no_copy_info.tx_head_size=0;/* Do not care because SEGMENTED*/
	no_copy_info.tx_trail_size=0; /* Do not care */
	no_copy_info.rx_head_mode=RX_HEADER_ON; /* RX = DATA received by SPP from ATP */
	no_copy_info.rx_head_size=SPP_RX_HEAD_SIZE;
	no_copy_info.rx_trail_size=SPP_RX_TRAIL_SIZE;
	no_copy_info.rx_mb=RVF_INVALID_MB_ID; /* Not set by SPP */
	no_copy_info.tx_mb=RVF_INVALID_MB_ID; /* Not set by SPP */
		
	return_status=atp_open_port_rsp(pending_port_info[i].initiator_id, pending_port_info[i].port_nb,atp_spp_sw_id,
		(T_ATP_PORT_NB) handle,port_info,no_copy_info, (T_ATP_CUSTOM_INFO*) custom_info_p,result);
	
	pending_port_info[i].initiator_id = ATP_INVALID_SWE_ID;

	return return_status;
}




/******************************************************************************
* Function name: atp_spp_port_closed_from_atp
*
* Description : Translate ATP_PORT_CLOSED into SPP_CLOSE_PORT
* 
*
* Parameters :  Message pointer
*
* Return     :   Standard error 
*				RV_OK if  OK
*
* History			: 0.1 (20-Marsh-2000) 
*
******************************************************************************/
T_RV_RET atp_spp_port_closed_from_atp(T_ATP_PORT_CLOSED * close_port_p)
{
	
	T_SPP_CLOSE_PORT * spp_close_port_p;
	T_ATP_PORT_NB handle;
	UINT8 i;
	
	handle = close_port_p->port_nb;

	/* Check that this port was not in opening mode */
	/* If it was in opening mode, then find it in the pending port array  */
	i=0;
	while(  ((pending_port_info[i].port_nb!=close_port_p->closer_port_nb) || 
		(pending_port_info[i].initiator_id!=close_port_p->closer_sw_id))       &&
		(i<ATP_SPP_MAX_PENDING_PORT))
	{
		i++;
	}

	if (i!=ATP_SPP_MAX_PENDING_PORT)
	{
		/* In this case, the port handle was in the pending port array */
		/* That means that the port has not been completely open (only RQST sent) */
		/* RV_OK or MEMORY ERROR */
		
		handle = pending_port_info[i].handle;
		pending_port_info[i].initiator_id = ATP_INVALID_SWE_ID; // Refresh value
		
		if (  (handle & SPP_HANDLE_TYPE) == SPP_SERVER_HANDLE_FLAG)
		{
			// Port was open in server mode 
			// So close server
			T_SPP_CLOSE_SERV *	close_server_p;		
			if (rvf_get_buf (spp_if_mb,sizeof(T_SPP_CLOSE_SERV),(void **) &close_server_p)==RVF_RED)
			{
				return RV_MEMORY_ERR;
			}
			close_server_p->handle = handle;
			close_server_p->os_hdr.msg_id = SPP_CLOSE_SERV_EVT;	
			rvf_send_trace("ATP/SPP : Send a SPP_CLOSE_SERV to SPP  ",40,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 			
			rvf_send_msg (spp_addr_id,close_server_p);
			return RV_OK;
		}
	}


	if (rvf_get_buf (spp_if_mb,sizeof(T_SPP_CLOSE_PORT),(void **) &spp_close_port_p)!=RVF_RED)
	{		
		spp_close_port_p->handle=handle;		
		spp_close_port_p->os_hdr.msg_id=SPP_CLOSE_PORT_EVT;		
		rvf_send_msg (spp_addr_id,spp_close_port_p);	
		return (RV_OK);
	}
	else 
	{
		return(RV_MEMORY_ERR);
	}
}








/******************************************************************************
* Function name: atp_spp_send_to_spp_buffer_nc
*
* Description : Translate ATP_NO_COPY_DATA_RDY into SPP_SEND_BUFFER_NC_EVT
* 
*
* Parameters :  Message pointer
*
* Return     :   Standard error 
*				RV_OK if  OK
*
* History			: 0.1 (20-Marsh-2000) 
*
******************************************************************************/
T_RV_RET atp_spp_send_to_spp_buffer_nc(T_ATP_NO_COPY_DATA_RDY * atp_no_copy_p)
{
	
	T_SPP_SEND_BUFFER_NC * spp_no_copy_p;
	
	if (rvf_get_buf (spp_if_mb,sizeof(T_SPP_SEND_BUFFER_NC),(void **) &spp_no_copy_p)!=RVF_RED)
	{
		
		spp_no_copy_p->handle=(T_SPP_HANDLE) atp_no_copy_p->port_nb;
		spp_no_copy_p->buffer=atp_no_copy_p->atp_buffer_p;
		spp_no_copy_p->length=(UINT16) atp_no_copy_p->buffer_size;
		
		
		spp_no_copy_p->os_hdr.msg_id=SPP_SEND_BUFFER_NC_EVT;
		
		rvf_send_msg (spp_addr_id,spp_no_copy_p);
		
		return (RV_OK);
	}
	else 
	{
		return(RV_MEMORY_ERR);
	}
}


/******************************************************************************
* Function name: atp_spp_set_spp_signals
*
* Description : Based on a ATP_SIGNAL_CHANGED signal, set SPP signals
* 
*
* Parameters :  Message pointer
*
* Return     :   Standard error 
*				RV_OK if  OK
*
* History			: 0.1 (20-Marsh-2000) 
*
******************************************************************************/
T_RV_RET atp_spp_set_spp_signals(T_ATP_SIGNAL_CHANGED * message_p)
{	
	T_SPP_LINE_STS * line_sts_p;

	/* Get Signals of the port on ATP side */

	
	ATP_SEND_TRACE("ATP/SPP : Received a ATP_SIGNAL_CHANGED  from ATP ",
		RV_TRACE_LEVEL_DEBUG_LOW); 

	rvf_send_trace("ATP/SPP : Signal value =  ",26,
		(UINT32) message_p->signal,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
	
	if (rvf_get_buf (spp_if_mb,sizeof(T_SPP_LINE_STS),(void **) &line_sts_p)==RVF_RED)
	{
		return RV_MEMORY_ERR;
	}
	
	line_sts_p->handle =((T_ATP_SIGNAL_CHANGED *) message_p)->port_nb;
	line_sts_p->mask =OTHER_SIGNALS;
	line_sts_p->os_hdr.msg_id =SPP_SET_LINE_STS_EVT;
	line_sts_p->fc_flow =FC_FLOW_ON; // Should be do not care 
	
	/* DCD */
	if ( (message_p->signal & ATP_DCD_UNMASK) == ATP_DCD_0)
	{
		line_sts_p->dv = DCD_0;
	}
	else
	{
		line_sts_p->dv = DCD_1;
	}
	
	/* RI */
	if ( (message_p->signal & ATP_RI_UNMASK) == ATP_RI_0)
	{
		line_sts_p->ic = RI_0;
	}
	else
	{
		line_sts_p->ic = RI_1;
	}
	
	
	/* DTR/DSR */
	if ( (message_p->signal & ATP_DTR_DSR_UNMASK) == ATP_DTR_DSR_0)
	{
		line_sts_p->rtc = DTRDSR_0;
	}
	else
	{
		line_sts_p->rtc = DTRDSR_1;
	}
	
	/* RTS CTS */
	if ( (message_p->signal & ATP_RTS_CTS_UNMASK) == ATP_RTS_CTS_0)
	{
		line_sts_p->rtr = RTSCTS_0;
	}
	else
	{
		line_sts_p->rtr = RTSCTS_1;
	}
	
	rvf_send_trace("ATP/SPP : Send a SPP_SET_LINE_STS to SPP  ",42,
		NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
	
	return rvf_send_msg (spp_addr_id,line_sts_p);					
}



/******************************************************************************
* Function name: atp_spp_set_atp_signals
*
* Description : Based on a SPP_LINE_STS 
* 
*
* Parameters :  Message pointer
*
* Return     :   Standard error 
*				RV_OK if  OK
*
* History			: 0.1 (20-Marsh-2000) 
*
******************************************************************************/
T_RV_RET atp_spp_set_atp_signals(T_SPP_LINE_STS * message_p)
{
	T_ATP_PORT_SIGNAL signal,old_signal;
	T_ATP_SIGNAL_CHANGE_MASK  mask = 0;
	
	rvf_send_trace("ATP/SPP : Received a LINE_STS event from SPP ",45,
		NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
	
	atp_get_signal(atp_spp_sw_id,(T_ATP_PORT_NB) ((T_SPP_LINE_STS *) message_p)->handle,
		&old_signal);
	
	signal=old_signal;
	
	/* DCD */
	if ( (message_p->dv  == DCD_0) && ( (old_signal & ATP_DCD_UNMASK) == ATP_DCD_1))
	{
		/* DCD changed to 0 */
		mask |= ATP_DCD_UNMASK;
		signal &= (~ ATP_DCD_UNMASK); // clear DCD
		ATP_SEND_TRACE("ATP : DCD has been set to 0",RV_TRACE_LEVEL_DEBUG_LOW);
	}
	else
	{
		if ( (message_p->dv  == DCD_1) && ( (old_signal & ATP_DCD_UNMASK) == ATP_DCD_0))
		{
			/* DCD changed to 1 */
			mask |= ATP_DCD_UNMASK;
			signal |= ATP_DCD_1;
			ATP_SEND_TRACE("ATP : DCD has been set to 1",RV_TRACE_LEVEL_DEBUG_LOW);
		}
	}
	
	/* RI */
	if ( (message_p->ic  == RI_0) && ( (old_signal & ATP_RI_UNMASK) == ATP_RI_1))
	{
		/* RI changed to 0 */
		mask |= ATP_RI_UNMASK;
		signal &= (~ ATP_RI_UNMASK); // clear RI
		ATP_SEND_TRACE("ATP : RI has been set to 0",RV_TRACE_LEVEL_DEBUG_LOW);
	}
	else
	{
		if ( (message_p->ic  == RI_1) && ( (old_signal & ATP_RI_UNMASK) == ATP_RI_0))
		{
			/* RIchanged to 1 */
			mask |= ATP_RI_UNMASK;
			signal |= ATP_RI_1;
			ATP_SEND_TRACE("ATP : RI has been set to 1",RV_TRACE_LEVEL_DEBUG_LOW);
		}
	}
	
	
	/* DTR/DSR */
	if ( (message_p->rtc  == DTRDSR_0) && ( (old_signal & ATP_DTR_DSR_UNMASK) == ATP_DTR_DSR_1))
	{
		/* DTR/DSR changed to 0 */
		mask |= ATP_DTR_DSR_UNMASK;
		signal &= (~ ATP_DTR_DSR_UNMASK); // clear DTR/DSR
		ATP_SEND_TRACE("ATP : DTR/DSR has been set to 0",RV_TRACE_LEVEL_DEBUG_LOW);
	}
	else
	{
		if ( (message_p->rtc  == DTRDSR_1) && ( (old_signal & ATP_DTR_DSR_UNMASK) == ATP_DTR_DSR_0))
		{
			/* DCD changed to 0 */
			mask |= ATP_DTR_DSR_UNMASK;
			signal |= ATP_DTR_DSR_1;
			ATP_SEND_TRACE("ATP : DTR/DSR has been set to 1",RV_TRACE_LEVEL_DEBUG_LOW);
		}
	}
	
	
	/* RTS CTS */
	if ( (message_p->rtr  == RTSCTS_0) && ( (old_signal & ATP_RTS_CTS_UNMASK) == ATP_RTS_CTS_1))
	{
		/* DTR/DSR changed to 0 */
		mask |= ATP_RTS_CTS_UNMASK;
		signal &= (~ ATP_RTS_CTS_UNMASK); // clear DTR/DSR
		ATP_SEND_TRACE("ATP : RTS/CTS has been set to 0",RV_TRACE_LEVEL_DEBUG_LOW);
	}
	else
	{
		if ( (message_p->rtr  == RTSCTS_1) && ( (old_signal & ATP_RTS_CTS_UNMASK) == ATP_RTS_CTS_0))
		{
			/* DCD changed to 0 */
			mask |= ATP_RTS_CTS_UNMASK;
			signal |= ATP_RTS_CTS_1;
			ATP_SEND_TRACE("ATP : RTS/CTS has been set to 1",RV_TRACE_LEVEL_DEBUG_LOW);
		}
	}
	
	
	rvf_send_trace("ATP/SPP : Signal Value = ",25,
		(UINT32) signal ,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
	rvf_send_trace("ATP/SPP : Mask  Value = ",24,
		(UINT32) mask ,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
	
	return atp_set_signal(atp_spp_sw_id, (T_ATP_PORT_NB) ((T_SPP_LINE_STS *) message_p)->handle,
		signal,mask);
}

	
	
