view src/cs/services/atp/atp_spp_api.c @ 685:3fb7384e820d

tpudrv12.h: FCDEV3B goes back to being itself A while back we had the idea of a FreeCalypso modem family whereby our current fcdev3b target would some day morph into fcmodem, with multiple FC modem family products, potentially either triband or quadband, being firmware-compatible with each other and with our original FCDEV3B. But in light of the discovery of Tango modules that earlier idea is now being withdrawn: instead the already existing Tango hw is being adopted into our FreeCalypso family. Tango cannot be firmware-compatible with triband OM/FCDEV3B targets because the original quadband RFFE on Tango modules is wired in TI's original Leonardo arrangement. Because this Leonardo/Tango way is now becoming the official FreeCalypso way of driving quadband RFFEs thanks to the adoption of Tango into our FC family, our earlier idea of extending FIC's triband RFFE control signals with TSPACT5 no longer makes much sense - we will probably never produce any new hardware with that once-proposed arrangement. Therefore, that triband-or-quadband FCFAM provision is being removed from the code base, and FCDEV3B goes back to being treated the same way as CONFIG_TARGET_GTAMODEM for RFFE control purposes.
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 24 Sep 2020 21:03:08 +0000
parents 945cf7f506b2
children
line wrap: on
line source

/*******************************************************************************
*
* 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);
}