view src/cs/services/atp/atp_gsm_bt_api.c @ 303:f76436d19a7a default tip

!GPRS config: fix long-standing AT+COPS chance hanging bug There has been a long-standing bug in FreeCalypso going back years: sometimes in the AT command bring-up sequence of an ACI-only MS, the AT+COPS command would produce only a power scan followed by cessation of protocol stack activity (only L1 ADC traces), instead of the expected network search sequence. This behaviour was seen in different FC firmware versions going back to Citrine, and seemed to follow some law of chance, not reliably repeatable. This bug has been tracked down and found to be specific to !GPRS configuration, stemming from our TCS2/TCS3 hybrid and reconstruction of !GPRS support that was bitrotten in TCS3.2/LoCosto version. ACI module psa_mms.c, needed only for !GPRS, was missing in the TCS3 version and had to be pulled from TCS2 - but as it turns out, there is a new field in the MMR_REG_REQ primitive that needs to be set correctly, and that psa_mms.c module is the place where this initialization needed to be added.
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 08 Jun 2023 08:23:37 +0000
parents 4e78acac3d88
children
line wrap: on
line source

/*******************************************************************************
*
* File Name : atp_gsm_bt_api.c
*
* This file handles all the interface between GSM AT command handler or Data handler
* and the BT protocol stack. It has 2 main functions:
*	- get the events coming from Bluetooth ATP in direction of GSM, analyse them and
*	  call the proper function of atp_gsm_gsm_api.c
*   - offer function to GSM so that GSM can use services of the BT PS
*
*
* Version number	: 0.1      Date : 10-Jully-2000
*
* History			: 0.1  - Created by E. Baissus
*
* Author			: Eric Baissus : e-baissus@ti.com
*
*   (C) Copyright 2000 by Texas Instruments Incorporated 
*****************************************************************************/

#include "rv/rv_general.h"
#include "rvf/rvf_api.h"
#include "atp/atp_api.h"
#include "atp/atp_config.h"
#include "atp/atp_messages.h"
#include "atp/atp_gsm_bt_api.h"
#include "atp/atp_gsm_gsm_api.h"
#include "atp/atp_config.h"
#include "atp/bti_at.h"
#include "atp/atp_i.h"
#include "rvm/rvm_use_id_list.h"

#include <string.h>

/* Internal definitions */



typedef enum
{
	ATP_ACTIVE , // Data exchange in the BT/GSM adapter is on going
	ATP_NOT_ACTIVE  // Data exchange in the BT/GSM adapter is not on going 
} T_ATP_DATA_ACTIVITY;

typedef enum
{
	CMD_PENDING, // GSM should be processing a command from BT
	CMD_NOT_PENDING // GSM can handle a new command issued by BT
} T_ATP_GSM_CMD_STATUS;

typedef struct
{
	UINT32 gsm_tx_data_left; // Number of data left to transmit to ATP
	T_ATP_DATA_ACTIVITY atp_tx_data_activity; // Indicates if data exchange is on going from BT to GSM
	T_ATP_GSM_CMD_STATUS cmd_status; 
	UINT32 bt_max_payload; 
	UINT16 tx_head_size;
	UINT16 tx_trail_size;
} T_ATP_GSM_PORT_STRUCT;


/* Definition used only in this file */
typedef enum
{
	ATP_GSM_OPEN_PORT_PENDING, // The adaptor is processing an open port
	ATP_GSM_OPEN_PORT_NOT_PENDING // The adaptor is not processing an open port
} T_ATP_GSM_OPEN_PORT_PENDING; 



 
/* Local variable */
static T_ATP_SW_ENTITY_ID atp_gsm_sw_id;	/* Any entity needs to register to ATP and then get an id											   This id will be identify GSM for ATP */
static T_ATP_PORT_NB initiator_port_nb;		/* Port number used by the SWE requesting a new port to GSM */
static T_ATP_SW_ENTITY_ID initiator_id;		/* Initiator ID of the SWE requesting to open a port with GSM  */
static T_ATP_GSM_OPEN_PORT_PENDING  open_port_pending; /* Value can be : PORT_PENDING or PORT_NOT_PENDING
													    A port is said to be in PORT_PENDING when a new port 
														has been requested but this new port is not yet created
														Only one port at a  time can be in PORT_PENDING state
														If open_port_pending is in PORT_PENDING state, then no 
														new port request is processed
														*/
static UINT8 current_nb_port; // Indicate number of port actually activated
static T_ATP_GSM_PORT_STRUCT * port_array[ATP_MAX_NB_OF_PORT_SUPPORTED_BY_GSM];
static UINT32 temp_bt_max_payload; // USed to store BT MFS before the port is actually open

/* Function definition */
static T_RV_RET atp_gsm_init_port(T_ATP_GSM_PORT_STRUCT * port_p);
static T_RV_RET atp_gsm_init_if(void);
static T_RV_RET atp_gsm_get_new_port_nb(UINT8 * port_nb);





/******************************************************************************
* Function name: atp_gsm_bt_event_handle
*
* Description : Main function used to split the events coming from ATP
*				and call proper function of GSM side (see atp_gsm_gsm_api.c)
* 
*
* Parameters :   * ATP message 
*
* Return     :   No return  
*				 
*
* History			: 0.1 (10-Jully-2000) 
*
******************************************************************************/
void atp_gsm_bt_event_handle(void * message_p)
{
	
	T_RV_RET error = RV_OK;
	T_BTI_PORT_NB port_nb = 0xFF;


	
	switch(((T_ATP_MESSAGE *) message_p)->msg_id)
	{
	case ATP_OPEN_PORT_IND : 
		{  
			T_BTI_BT_PORT_INFO bt_port_info;
			rvf_send_trace("ATP/GSM : Received a ATP_OPEN_PORT_IND from ATP   ",50,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID);
			
			// Store initiator parameters
			initiator_port_nb=(( T_ATP_OPEN_PORT_IND *) message_p)->initiator_port_nb;
			initiator_id = (( T_ATP_OPEN_PORT_IND *) message_p)->initiator_id;

			if ((open_port_pending == ATP_GSM_OPEN_PORT_PENDING) || (atp_gsm_get_new_port_nb(&port_nb)!= RV_OK))
			{ 
				// A port opening is pending : refuse to open a new port
				T_ATP_PORT_INFO dummy_port_info;
				T_ATP_NO_COPY_INFO dummy_no_copy_info;
			
			rvf_send_trace("ATP/GSM : Failed to open a port : port opening was pending or max number of port has been reached",97,
					NULL_PARAM,RV_TRACE_LEVEL_WARNING,ATP_USE_ID);
			
			/* Initialise to avoid warning */
			memset(&dummy_port_info,0,sizeof(dummy_port_info));
			memset(&dummy_no_copy_info,0,sizeof(dummy_no_copy_info));

			// Send a negative response to ATP 
			atp_open_port_rsp((( T_ATP_OPEN_PORT_IND *) message_p)->initiator_id,initiator_port_nb,atp_gsm_sw_id,0,
				dummy_port_info,dummy_no_copy_info,NULL,OPEN_PORT_NOK);
			rvf_free_buf( (( T_ATP_OPEN_PORT_IND *) message_p)->custom_info_p );
			error=RV_NOT_SUPPORTED;
			}			
			
			// Send open port indication to GSM
			/////////////// Need to update data packet size
			bt_port_info.optimal_bt_max_packet_size  = ((T_ATP_CUSTOM_TO_GSM_INFO *) (( T_ATP_OPEN_PORT_IND *) message_p)->custom_info_p)->bt_max_payload; // DO NOT CARE ...
			temp_bt_max_payload = bt_port_info.optimal_bt_max_packet_size; // Store temporaly the MFS 
			open_port_pending=ATP_GSM_OPEN_PORT_PENDING; // Now , an open port is pending
			bti_at_open_port_ind(port_nb,bt_port_info);
			rvf_free_buf( (( T_ATP_OPEN_PORT_IND *) message_p)->custom_info_p );
			break;
		};
		
		
	case ATP_PORT_CLOSED : 
		{  // A close_port has been issue on BT side
			rvf_send_trace("ATP/GSM : Received a ATP_PORT_CLOSED  from ATP    ",50,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			
			// Send close port indication to GSM 
			bti_at_close_port_ind((T_BTI_PORT_NB) ((T_ATP_PORT_CLOSED *) message_p)->port_nb); 			
			break;
		};
		
		
	case ATP_TXT_CMD_RDY : 
		{  // A command in text format has been issued by BT side
			rvf_send_trace("ATP/GSM : Received a ATP_TXT_CMD_RDY from ATP",45,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			
			if (((T_ATP_TXT_CMD_RDY *) message_p)->cmd_type == CMD_ABORT)
			{
				rvf_send_trace("ATP/GSM : An abort command is requested by ATP ",47,
					NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
				port_array[((T_ATP_TXT_CMD_RDY *)message_p)->port_nb]->cmd_status = CMD_NOT_PENDING;
				bti_at_abort_ind((T_BTI_PORT_NB) ((T_ATP_TXT_CMD_RDY *) message_p)->port_nb);
			}
			else
			{
				rvf_send_trace( ((T_ATP_TXT_CMD_RDY *) message_p)->txt_cmd_p,
					(UINT8) strlen(((T_ATP_TXT_CMD_RDY *) message_p)->txt_cmd_p),
					NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
				port_array[((T_ATP_TXT_CMD_RDY *)message_p)->port_nb]->cmd_status = CMD_PENDING;
				bti_at_cmd_ind((T_BTI_PORT_NB) ((T_ATP_TXT_CMD_RDY *) message_p)->port_nb, 
					(char *) ((T_ATP_TXT_CMD_RDY *) message_p)->txt_cmd_p);
			}
			
			atp_free_buffer(((T_ATP_TXT_CMD_RDY *) message_p)->txt_cmd_p);			
			break;
		};
		
	case ATP_CMD_RDY : 
		{  // A command in binary format has been issued by BT side
			// This command is ignored since binary format not supported by GSM
			rvf_send_trace("ATP/GSM : Ignored a ATP_CMD_RDY from ATP",40,
				NULL_PARAM,RV_TRACE_LEVEL_WARNING, ATP_USE_ID); 
			
			atp_free_buffer(((T_ATP_CMD_RDY *) message_p)->cmd_info_p);
			
			break;
		};
		
		
	case ATP_NO_COPY_DATA_RDY : 
		{  // BT side issued a no copy format buffer to GSM
			// This command is ignored and warning is raised
			rvf_send_trace("ATP/GSM : Ignored a ATP_NO_COPY_DATA_RDY from ATP ",50,
				NULL_PARAM,RV_TRACE_LEVEL_WARNING, ATP_USE_ID); 
			
			atp_free_buffer(((T_ATP_NO_COPY_DATA_RDY *) message_p)->atp_buffer_p);
			
			break;
		};
		
		
		
	case ATP_DATA_RDY : 
		{  // BT side has sent data to GSM
			rvf_send_trace("ATP/GSM : Received a ATP_DATA_RDY from ATP . Nb of data = ",58,
				(UINT32) ((T_ATP_DATA_RDY *)message_p)->nb_bytes,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			
			/* If GSM is not currently handling data exchange, call bti_data_rdy */
			if (port_array[((T_ATP_DATA_RDY *)message_p)->port_nb]->atp_tx_data_activity == ATP_NOT_ACTIVE)
			{
				port_array[((T_ATP_DATA_RDY *)message_p)->port_nb]->atp_tx_data_activity = 
					ATP_ACTIVE;

				rvf_send_trace("ATP/GSM : bti_data_ready_ind has been called by BT . Nb_Bytes =  ",65,
					(UINT32) ((T_ATP_DATA_RDY *)message_p)->nb_bytes ,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
				
				bti_data_ready_ind((T_BTI_PORT_NB) ((T_ATP_DATA_RDY *)message_p)->port_nb,
					(unsigned long) ((T_ATP_DATA_RDY *)message_p)->nb_bytes);

			}
			else
			{
				UINT8 * dummy_data_buffer = NULL;
				UINT32 data_left,data_read;
				
				ATP_SEND_TRACE("ATP/GSM : Wait before sending data to GSM since GSM is already fetching data",
					RV_TRACE_LEVEL_DEBUG_LOW); 

			   atp_get_data(atp_gsm_sw_id,((T_ATP_DATA_RDY *)message_p)->port_nb,(UINT8 *) dummy_data_buffer,
		               (UINT32) 0,&data_read,&data_left);

				rvf_send_trace("ATP/GSM : Total number of data to fetch for GSM =  ",51,
					(UINT32) data_left,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			}
			
			break;
		};			
	
		
		
	case ATP_PORT_MODE_CHANGED : 
		{  // BT side has issue a port mode changed (Data or Command)
			rvf_send_trace("ATP/GSM : Received a ATP_PORT_MODE_CHANGED from ATP",51,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			
			if( ((T_ATP_PORT_MODE_CHANGED *) message_p)->mode == ATP_PORT_DATA_MODE)
			{
				ATP_SEND_TRACE("ATP/GSM: switch to data mode",RV_TRACE_LEVEL_DEBUG_LOW);
				ATP_SEND_TRACE("ATP/GSM: BT calls bti_data_ready_cnf in order to accept data from GSM",RV_TRACE_LEVEL_DEBUG_LOW);
				bti_data_ready_cnf((T_BTI_PORT_NB) ((T_ATP_PORT_MODE_CHANGED *) message_p)->port_nb); 
			}
			else
			{
				ATP_SEND_TRACE("ATP/GSM: port has been switched to command mode by BT",RV_TRACE_LEVEL_DEBUG_LOW);
			} 
			
			break;
		};
		
		
	case ATP_SIGNAL_CHANGED : 
		{  // BT side has issued a signal change
			rvf_send_trace("ATP/GSM : Received a ATP_SIGNAL_CHANGED from ATP",48,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			
			if ( ( (((T_ATP_SIGNAL_CHANGED *) message_p)->mask) & ATP_TX_FLOW_UNMASK) != 0) 
			{			
				// change on TX flow
				if( ( (((T_ATP_SIGNAL_CHANGED *) message_p)->mask) &
					(((T_ATP_SIGNAL_CHANGED *) message_p)->signal) ) == ATP_TX_FLOW_OFF)
				{			
					// BT side has switch TX GSM flow to OFF
					rvf_send_trace("ATP/GSM : ATP requested TX GSM Flow to be OFF",45,
						NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
				}
				else
				{
					// BT side has switch TX GSM flow to ON
					rvf_send_trace("ATP/GSM : ATP requested TX GSM Flow to be ON",44,
						NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
					
					if (port_array[((T_ATP_SIGNAL_CHANGED *) message_p)->port_nb]->gsm_tx_data_left != 0)
					{
						// Retry to send data to ATP
						bti_data_ready_req( (T_BTI_PORT_NB) ((T_ATP_SIGNAL_CHANGED *) message_p)->port_nb,
										port_array[((T_ATP_SIGNAL_CHANGED *) message_p)->port_nb]->gsm_tx_data_left);
					}
				} 
				break;
			} 

			//////////////////////////////////////
			// Otherwise, ignore the signal change
			/////////////////////TO BE UPDATED !!! /////////////////
			rvf_send_trace("ATP/GSM : Signal change has been ignored ",41,
				NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
		
			break;
		};
		
		
	default:
		{
			rvf_send_trace("ATP/GSM : Unknown message received from ATP by ATP_GSM => ignored ",66,
				NULL_PARAM,RV_TRACE_LEVEL_WARNING,ATP_USE_ID); 
			break;
		};
	}
	
	/* Release ATP message buffer */
	atp_free_message(message_p);
	
}




/******************************************************************************
* Function name: bti_at_init_req
*
* Description : This function is called by GSM to initialise GSM with ATP
* 
*
* Parameters :  None
*
* Return     :   BTI_AT_OK or BTI_AT_INTERNAL_ERR
*
* History			: 0.1 (10-Jully-2000) 
*					: 0.2 (02-Jan-2001) 
******************************************************************************/
void bti_at_init_req(void)
{
	T_ATP_ENTITY_MODE mode;
	T_ATP_SW_ENTITY_NAME name;
	T_ATP_CALLBACK return_path;
	
	ATP_SEND_TRACE("ATP/GSM : bti_at_init_req has been called by GSM .  ",
		RV_TRACE_LEVEL_DEBUG_LOW); 
	
	/* Static variable initialisation */
	atp_gsm_init_if();

	/* Register GSM to ATP */
	strcpy((char *) name,ATP_GSM_NAME);
	return_path.callback_func = atp_gsm_bt_event_handle;
	return_path.addr_id = RVF_INVALID_ADDR_ID;
	
	mode.cmd_mode=TXT_MODE; 
	mode.cp_mode=COPY_ON;
	mode.cmd_support_mode=CMD_SUPPORT_ON;
	
	if(atp_reg(name,return_path,mode,&atp_gsm_sw_id)!=RV_OK)
	{
		rvf_send_trace("ATP_GSM: GSM entity registration failed ",39, NULL_PARAM ,
			RV_TRACE_LEVEL_WARNING,ATP_USE_ID); 
		bti_at_init_cnf(BTI_NAK); // Failed registration
	}
	else
	{
		ATP_SEND_TRACE ("ATP/GSM: GSM entity registration succeeded ",RV_TRACE_LEVEL_DEBUG_LOW); 
		bti_at_init_cnf(BTI_ACK); // Succeeded registration
	}
}




/******************************************************************************
* Function name: bti_at_deinit_ind
*
* Description : This function is called by GSM (?) to de-initialise GSM from ATP
* 
*
* Parameters :  None
*
* Return     :   BTI_AT_OK or BTI_AT_NOT_SUPPORTED 
*				
*
* History			: 0.1 (10-Jully-2000) 
*
******************************************************************************/
void bti_at_deinit_req(void)
{
	ATP_SEND_TRACE ("ATP_GSM: bti_at_deinit_req has been called by GSM ",RV_TRACE_LEVEL_DEBUG_LOW); 
	atp_dereg(atp_gsm_sw_id);	
}



/******************************************************************************
* Function name: bti_at_deinit_res
*
* Description : This function is called by GSM to de-initialise GSM from ATP
* 
*
* Parameters :  None
*
* Return     :   BTI_AT_OK or BTI_AT_NOT_SUPPORTED 
*				
*
* History			: 0.1 (10-Jully-2000) 
*
******************************************************************************/
void bti_at_deinit_res(void)
{
// DUMMY FUNCTION
}



/******************************************************************************
* Function name: bti_at_open_port_res
*
* Description : This function is called by GSM to accept or refuse
*				an open port request issued by BT side
*
*
*	
*
* History			: 0.1 (10-Jully-2000) 
*					: 0.2 (02-Jan-2001) 
******************************************************************************/
void bti_at_open_port_res(T_BTI_PORT_NB gsm_port_nb,
						  T_BTI_GSM_PORT_INFO gsm_port_info,
						  T_BTI_ACK ack)
{
	
	T_ATP_PORT_INFO port_info ;
	T_ATP_NO_COPY_INFO no_copy_info ;
	T_RV_RET return_status;
	T_ATP_CUSTOM_FROM_GSM_INFO * custom_gsm_info_p;
	T_ATP_OTHER_PORT_END_INFO   other_end_info;
	
	rvf_send_trace("ATP/GSM : bti_at_open_port_res has been called by GSM . Flag = ",43,
		(UINT32) ack,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
	rvf_send_trace("ATP/GSM : gsm_port_nb = ",24,
		(UINT32) gsm_port_nb,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
	rvf_send_trace("ATP/GSM : GSM indication for MFS = ",35,
		(UINT32) gsm_port_info.optimal_gsm_max_packet_size,
		RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
	
	/* Get information on the other end port */
	if (atp_get_info_on_port_end(initiator_id,(T_ATP_PORT_NB) initiator_port_nb,
		&other_end_info) != RV_OK)
	{
		ATP_SEND_TRACE("ATP : Failed to get information on other end port ",
			RV_TRACE_LEVEL_WARNING);
		no_copy_info.tx_head_size = 0;
		no_copy_info.tx_trail_size = 0;
	}
	else
	{
		no_copy_info.tx_head_size = other_end_info.no_copy_info.rx_head_size;
		no_copy_info.tx_trail_size = other_end_info.no_copy_info.rx_trail_size;
	}


	/* Initialise port information  */
	no_copy_info.rx_head_mode = RX_HEADER_OFF; // COPY ON mode in RX 
	no_copy_info.tx_head_mode = TX_HEADER_OFF; // COPY OFF mode in TX for optimization

	
	//	no_copy_info.tx_head_mode = TX_HEADER_ON; // COPY OFF mode in TX for optimization
	////////// SHOULD BE REMOVED IN CASE GSM SEND DATA WITH HEADER AND TRAILER BIT //////
	no_copy_info.tx_head_size = 0;
	no_copy_info.tx_trail_size = 0;

	no_copy_info.rx_mb = RVF_INVALID_MB_ID;
	no_copy_info.tx_mb = RVF_INVALID_MB_ID;
	no_copy_info.packet_mode  = NORMAL_PACKET; /* No L2CAP packet... */
	
	port_info.dce_mask[0]=0x0000; // Do not care, GSM is not in DCE_ON mode
	port_info.ring_type=ATP_NO_RING_TYPE;
	port_info.signal_mask=ATP_TX_FLOW_UNMASK;
	
	/* Store custom info from GSM */		
	atp_get_buffer(sizeof(T_ATP_CUSTOM_FROM_GSM_INFO),(void **) &custom_gsm_info_p);
	custom_gsm_info_p->custom_type = ATP_FROM_GSM_INFO;
	custom_gsm_info_p ->optimal_gsm_max_packet_size = gsm_port_info.optimal_gsm_max_packet_size;
	
	if (ack == BTI_ACK)
	{ 
		ATP_SEND_TRACE("ATP/GSM : GSM accepted to open a port ", RV_TRACE_LEVEL_DEBUG_LOW);
		// Initialise a new port 
		atp_get_buffer(sizeof(T_ATP_GSM_PORT_STRUCT),(void **) &(port_array[gsm_port_nb]));
		
		atp_gsm_init_port(port_array[gsm_port_nb]);
		port_array[gsm_port_nb]->tx_head_size = no_copy_info.tx_head_size;
		port_array[gsm_port_nb]->tx_trail_size = no_copy_info.tx_trail_size;

		return_status = atp_open_port_rsp( initiator_id,
										   (T_ATP_PORT_NB) initiator_port_nb,
										   atp_gsm_sw_id,
										   (T_ATP_PORT_NB) gsm_port_nb,
											port_info,
											no_copy_info,
											(T_ATP_CUSTOM_INFO *) custom_gsm_info_p,
											OPEN_PORT_OK);
	}
	else
	{ 
		rvf_send_trace("ATP/GSM : GSM refused the open port ",36,
			NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
		
		return_status = atp_open_port_rsp( initiator_id,
										   (T_ATP_PORT_NB) initiator_port_nb,
										   atp_gsm_sw_id,
										   (T_ATP_PORT_NB) gsm_port_nb,
											port_info,
											no_copy_info,
											NULL,
											OPEN_PORT_NOK);
	}
	
	if(return_status != RV_OK)
	{
		rvf_send_trace("ATP/GSM : Failed to open a port  ",33,
			NULL_PARAM,RV_TRACE_LEVEL_WARNING, ATP_USE_ID); 
	}
	
	open_port_pending = ATP_GSM_OPEN_PORT_NOT_PENDING;
}




/******************************************************************************
* Function name: bti_at_close_port_res
*
* Description : Not used by BT PS - Port is always closed
*
* Parameters :  
*
* Return     :   BTI_AT_OK 
*
* History			: 0.1 (10-Jully-2000) 
*
******************************************************************************/
void bti_at_close_port_res(T_BTI_PORT_NB gsm_port_nb)
{
	rvf_send_trace("ATP/GSM : bti_at_close_port_res has been called by GSM . Port nb = ",67,
		(UINT32) gsm_port_nb,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
	
	/* Memory Deallocation */
	rvf_free_buf(port_array[gsm_port_nb]);
	port_array[gsm_port_nb]=NULL;
}



/******************************************************************************
* Function name: bti_at_cmd_res
*
* Description : This function is called by GSM to provide result to BT
*
* Parameters :  gsm_port_nb = number of the gsm port
*				cmd = command in text format
*
* Return     :   BTI_AT_OK  or BTI_AT_NOT_SUPPORTED
*				
*
* History			: 0.1 (10-Jully-2000) 
*
******************************************************************************/
void bti_at_cmd_res(T_BTI_PORT_NB gsm_port_nb,
					char * cmd)
{
	T_ATP_TXT_CMD txt_buffer_p;

	ATP_SEND_TRACE ("ATP/GSM : bti_at_cmd_res has been called by GSM . Result is :  ",
		RV_TRACE_LEVEL_DEBUG_LOW); 
	rvf_send_trace(cmd,(UINT8) strlen(cmd),
		NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 

	/* Create a BTF buffer and copy command into. The command must be 0-terminated */
	atp_get_buffer(strlen(cmd) + 0x00000001,(void **) &txt_buffer_p);
	strcpy(txt_buffer_p,cmd);

	port_array[gsm_port_nb]->cmd_status = CMD_NOT_PENDING;
	if (atp_send_txt_cmd(atp_gsm_sw_id,(T_ATP_PORT_NB)  gsm_port_nb,
		RESULT_CODE,(T_ATP_TXT_CMD) txt_buffer_p) != RV_OK)
	{
		rvf_send_trace("ATP/GSM : Error when sending a command to ATP ",46,
			NULL_PARAM,RV_TRACE_LEVEL_WARNING, ATP_USE_ID); 
	}
}


/******************************************************************************
* Function name: bti_at_cmd_req
*
* Description : This function is called by GSM to provide preliminary result to BT
*				The end of the result will be issed via bti_at_cmd_res
*
* Parameters :  gsm_port_nb = number of the gsm port
*				cmd = command in text format
*
* Return     :   BTI_AT_OK  or BTI_AT_NOT_SUPPORTED
*				
*
* History			: 0.1 (10-Jully-2000) 
*
******************************************************************************/
void bti_at_cmd_req(T_BTI_PORT_NB gsm_port_nb,
					char * cmd)
{

	T_ATP_CMD_TYPE cmd_type;
	T_ATP_TXT_CMD txt_buffer_p;
	ATP_SEND_TRACE("ATP/GSM : bti_at_cmd_req has been called by GSM. Code is : ",
		RV_TRACE_LEVEL_DEBUG_LOW); 
	rvf_send_trace(cmd,(UINT8) strlen(cmd),
		NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 

	/* Create a BTF buffer and copy command into. The command must be 0-terminated */
	atp_get_buffer(strlen(cmd) + 0x00000001,(void **) &txt_buffer_p);
	strcpy(txt_buffer_p,cmd);

	if (port_array[gsm_port_nb]->cmd_status == CMD_PENDING)
	{
		cmd_type = PRELIMINARY_RESULT_CODE;
	}
	else
	{
		cmd_type = UNSOLICITED_RESULT;
	}

	if (atp_send_txt_cmd(atp_gsm_sw_id,(T_ATP_PORT_NB)  gsm_port_nb,cmd_type,
		(T_ATP_TXT_CMD) txt_buffer_p) != RV_OK)
	{
		rvf_send_trace("ATP/GSM : Error when sending a command to ATP ",46,
			NULL_PARAM,RV_TRACE_LEVEL_WARNING, ATP_USE_ID); 
	}

	bti_at_cmd_cnf(gsm_port_nb); // Accept new results 
}



/******************************************************************************
* Function name: bti_at_abort_res
*
* Description : This function is called by GSM to comfirm a command abort
*				NOT USED BY ATP YET
*
* Parameters :  gsm_port_nb = number of the gsm port
*
* Return     :   BTI_AT_NOT_SUPPORTED 
*				
*
* History			: 0.1 (10-Jully-2000) 
*
******************************************************************************/
void bti_at_abort_res(T_BTI_PORT_NB gsm_port_nb)
{
	rvf_send_trace("ATP/GSM : bti_at_abort_res has been called by GSM . Ignored . Port nb = ",72,
		(UINT32) gsm_port_nb,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 

	// Not implemented yet . Maybe usefull to send a commande back to indicate the abortion has succeede (or failed ...)
}


/******************************************************************************
* Function name: bti_data_ready_req
*
* Description : This function is called by GSM to indicate that data are 
*				available for BT PS.
*				 				
*
* Parameters :  gsm_port_nb = number of the gsm port
*				nb_bytes_available = number of bytes of data available
*
* Return     :  None
*
* History			: 0.1 (10-Jully-2000) 
*					  0.2 (01-Jan-2001) 
*
******************************************************************************/
void bti_data_ready_req (T_BTI_PORT_NB gsm_port_nb,
						 unsigned long  nb_bytes_available)
{
	UINT32 nb_bytes_left,nb_bytes_to_transmit;
	UINT8 * data_buffer_p;
	
	rvf_send_trace("ATP/GSM : data_ready_req has been called by GSM . Nb Bytes = ",61,
		(UINT32) nb_bytes_available,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
	
	rvf_send_trace("ATP/GSM : Port Number used by GSM  = ",37,
		(UINT32) gsm_port_nb,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
	
	if  (nb_bytes_available !=0) 
	{
		
		nb_bytes_left= nb_bytes_available; // number of byte to transmit in this function 
		
		while(nb_bytes_left > 0)
		{
			if (nb_bytes_left > port_array[gsm_port_nb]->bt_max_payload) // Bigger than allowed MFS
			{
				nb_bytes_to_transmit = port_array[gsm_port_nb]->bt_max_payload;
			}
			else
			{
				nb_bytes_to_transmit = nb_bytes_left;
			}
			
			
			/* This code is removed because of an issue with header and trailer size
			/* It is temporary remplaced by setting to 0 header and trailer */
			/*			atp_buffer_size = nb_bytes_to_transmit + port_array[(T_ATP_PORT_NB) gsm_port_nb]->tx_head_size+
			//				port_array[(T_ATP_PORT_NB) gsm_port_nb]->tx_trail_size;
			//
			//			rvf_send_trace("ATP/GSM : Buffer_size to send to ATP =  ",40,
			//				(UINT32) atp_buffer_size,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			//			
			//			rvf_send_trace("ATP/GSM : tx_header size = ",27,
			//				(UINT32) port_array[(T_ATP_PORT_NB) gsm_port_nb]->tx_head_size,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			//			
			//			rvf_send_trace("ATP/GSM : tx_trail  size = ",27,
			//				(UINT32) port_array[(T_ATP_PORT_NB) gsm_port_nb]->tx_trail_size,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			
			  
				if (atp_get_buffer_from_tx_mb(atp_gsm_sw_id,gsm_port_nb,atp_buffer_size,
				(void **) &data_buffer_p) == RV_OK)
				{
				/* Copy GSM data 
				rvf_send_trace("ATP/GSM : BT calls bti_get_gsm_data and request nb Bytes = ",59,
				(UINT32) nb_bytes_to_transmit,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
				
				  bti_get_gsm_data(gsm_port_nb,(char *) &(data_buffer_p[port_array[(T_ATP_PORT_NB) gsm_port_nb]->tx_head_size]),nb_bytes_to_transmit);
				  atp_no_copy_send_data(atp_gsm_sw_id,gsm_port_nb,data_buffer_p,nb_bytes_to_transmit);
				  nb_bytes_left -= nb_bytes_to_transmit;
				  port_array[gsm_port_nb]->gsm_tx_data_left = nb_bytes_left;
				  }
				  else
				  {
				  port_array[gsm_port_nb]->gsm_tx_data_left = nb_bytes_left;
				  nb_bytes_left = 0; // Flow control has been activated : wait for FLOW ON flag
		} */
			
			///////// START  REPLACEMENT CODE ////////////////


			if (atp_get_buffer_from_tx_mb(atp_gsm_sw_id,gsm_port_nb,nb_bytes_to_transmit,
				(void **) &data_buffer_p) == RV_OK)
			{
				/* Copy GSM data  */
				rvf_send_trace("ATP/GSM : BT calls bti_get_gsm_data and request nb Bytes = ",59,
					(UINT32) nb_bytes_to_transmit,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
				
				bti_get_gsm_data(gsm_port_nb,(char *) (data_buffer_p),nb_bytes_to_transmit);
				atp_no_copy_send_data(atp_gsm_sw_id,gsm_port_nb,data_buffer_p,nb_bytes_to_transmit);
				nb_bytes_left -= nb_bytes_to_transmit;
				port_array[gsm_port_nb]->gsm_tx_data_left = nb_bytes_left;
			}
			else
			{
				port_array[gsm_port_nb]->gsm_tx_data_left = nb_bytes_left;
				nb_bytes_left = 0; // Flow control has been activated : wait for FLOW ON flag
			} 
			
//			for (i=0;i<nb_bytes_to_transmit;i++)
//			{
//				rvf_send_trace("ATP/GSM : byte received from  GSM = ",
//					36,	(UINT32) (data_buffer_p[i]) ,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
//			}
			
		}
		///////// END REPLACEMENT CODE ////////////////
		
		
		if (port_array[gsm_port_nb]->gsm_tx_data_left == 0)
		{
			ATP_SEND_TRACE("ATP/GSM: BT got all the data from GSM . BT calls bti_data_ready_cnf 	",RV_TRACE_LEVEL_DEBUG_LOW);
			bti_data_ready_cnf(gsm_port_nb); // Acknowledge data copy to GSM
		}
	}
}






/******************************************************************************
* Function name: bti_get_bt_data
*
* Description : This function is called by GSM to get data from BT side . 
*				Copy is processed by BT side
*
* Parameters :  gsm_port_nb = number of the gsm port
*				data_buffer = pointer on a buffer in which data can be copied  
*				nb_bytes_to_copy = number of bytes to copy into data_buffer
*
* Return     :  None 
*			
*
* History			: 0.1 (10-Jully-2000) 
*					  0.2 (01-Jan-2001) 
*
******************************************************************************/
void bti_get_bt_data (T_BTI_PORT_NB gsm_port_nb,
					  char * data_buffer, 
					  unsigned long nb_bytes_to_copy)
{
	UINT32 data_left,data_read;
	
	
	rvf_send_trace("ATP/GSM : bti_get_bt_data has been called by GSM . Requested nb of data = ",
		74,	(UINT32) nb_bytes_to_copy ,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
	
	if ( (atp_get_data(atp_gsm_sw_id,gsm_port_nb,(UINT8 *) data_buffer,
		(UINT32) nb_bytes_to_copy,&data_read,&data_left) != RV_OK) ||
		(data_read != (UINT32) nb_bytes_to_copy))
	{
		ATP_SEND_TRACE("ATP/GSM : Could not get data from BT for GSM",RV_TRACE_LEVEL_ERROR);
	}
	
//	for (i=0;i<nb_bytes_to_copy;i++)
//	{
//		rvf_send_trace("ATP/GSM : byte sent to GSM = ",
//			29,	(UINT32) (data_buffer[i]) ,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
//	}
	
}


/******************************************************************************
* Function name: bti_data_ready_res
*
* Description : This function is called by GSM to indicate that it can receive 
*				new data from BT PS
*				 				
*
* Parameters :  gsm_port_nb = number of the gsm port
*
* Return     :  None
*
* History			: 0.1 (10-Jully-2000) 
*					  0.2 (01-Jan-2001) 
*
******************************************************************************/
void bti_data_ready_res (T_BTI_PORT_NB gsm_port_nb)
{
	UINT8 * dummy_data_buffer = NULL;
	UINT32 data_left,data_read;

	rvf_send_trace("ATP/GSM : bti_data_ready_res has been called by GSM ",52,
		NULL_PARAM,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 

	rvf_send_trace("ATP/GSM : port_number =  ",25,
		(UINT32) gsm_port_nb,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 

	/* Use the function atp_get_data to check if there are still data to transmit */
	if (atp_get_data(atp_gsm_sw_id,gsm_port_nb,(UINT8 *) dummy_data_buffer,
		               (UINT32) 0,&data_read,&data_left) != RV_OK)
	{
		ATP_SEND_TRACE("ATP/GSM : Could not get number of data to read from BT to GSM ",RV_TRACE_LEVEL_ERROR);
	}
	else
	{
			rvf_send_trace("ATP/GSM : data_left = ",22,
		(UINT32) data_left,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 


		if (data_left != 0)
		{
			rvf_send_trace("ATP/GSM : bti_data_ready_ind has been called by BT . Nb_Bytes =  ",65,
				(UINT32) data_left ,RV_TRACE_LEVEL_DEBUG_LOW, ATP_USE_ID); 
			
			bti_data_ready_ind(gsm_port_nb,(unsigned long) data_left);
		}
		else
		{
			port_array[gsm_port_nb]->atp_tx_data_activity = 
				ATP_NOT_ACTIVE;
			ATP_SEND_TRACE("ATP/GSM : ATP is ready to send new data to GSM ."
				,RV_TRACE_LEVEL_DEBUG_LOW); 

		}
	}
}


/******************************************************************************
* Function name: atp_gsm_init_if
*
* Description : This function initialise the GSM/BT adaptor
*				 
*				
*
*
* Return     :  RV_OK
*
* History			: 0.1 (10-Jully-2000) 
*
******************************************************************************/
T_RV_RET atp_gsm_init_if(void)
{
	UINT8 i;
	
	open_port_pending = ATP_GSM_OPEN_PORT_NOT_PENDING; 
	atp_gsm_sw_id = ATP_INVALID_SWE_ID;
	initiator_id = ATP_INVALID_SWE_ID;
	initiator_port_nb = (T_ATP_PORT_NB) 0xFF;
	current_nb_port = 0;
	for (i=0;i<ATP_MAX_NB_OF_PORT_SUPPORTED_BY_GSM;i++)
	{
		port_array[i]=NULL;
	}
	
	return RV_OK;
}



/******************************************************************************
* Function name: bti_at_signal_change_req
*
* Description : This function is called by GSM to provide a new signal line status 
*				to BT
*				 				
*
* Parameters :  gsm_port_nb = number of the gsm port
*				dce_signal = signal value
*				ring_type_1 = voice, data or fax
*				ring_type_2 = not used
*
* Return     :  None
*
* History			: 0.1 (01-Jan-2001) 
*
******************************************************************************/
void bti_at_signal_change_req (T_BTI_PORT_NB gsm_port_nb,
							   T_BTI_AT_DCE_SIGNAL dce_signal,
							   T_BTI_AT_RING_TYPE ring_type_1,
							   T_BTI_AT_RING_TYPE ring_type_2)
{
	T_ATP_PORT_SIGNAL old_signal,new_signal = 0;
	T_ATP_SIGNAL_CHANGE_MASK mask = 0 ;
	
	ATP_SEND_TRACE("ATP/GSM : bti_at_signal_change_req has been called by GSM ",
		RV_TRACE_LEVEL_DEBUG_LOW); 

	atp_get_signal(atp_gsm_sw_id,gsm_port_nb,&old_signal);
	
	if ( (dce_signal & BTI_AT_RING_MASK) == BTI_AT_RING_ON) // RING is ON
	{
		if ( (old_signal & ATP_RI_UNMASK) == ATP_RI_0) // RING is ON and was previously OFF 
		{
			T_ATP_RING_TYPE atp_ring_type;
			T_ATP_SW_NB sender_sw_nb;
			T_ATP_PORT_STRUCT * port_p;

			switch (ring_type_1)
			{

				/* Transparent data */
				case BTI_AT_RING_Async:
					{
						atp_ring_type = ATP_DATA_RING_TYPE;
						ATP_SEND_TRACE("ATP/GSM : RING_OFF -> RING_ON (Transparent data) "
							,RV_TRACE_LEVEL_DEBUG_LOW); 
						break;
					}

				/* Non transparent data */
				case BTI_AT_RING_RelAsync:
					{
						atp_ring_type = ATP_DATA_RING_TYPE;
						ATP_SEND_TRACE("ATP/GSM : RING_OFF -> RING_ON (Non-transparent data) "
							,RV_TRACE_LEVEL_DEBUG_LOW); 
						break;
					}

				/* Fax */
				case BTI_AT_RING_Fax:
					{
						atp_ring_type = ATP_FAX_RING_TYPE;
						ATP_SEND_TRACE("ATP/GSM : RING_OFF -> RING_ON (Fax) "
							,RV_TRACE_LEVEL_DEBUG_LOW); 
						break;
					}

				/* Voice */
				case BTI_AT_RING_Voice:
					{
						atp_ring_type = ATP_VOICE_RING_TYPE;
						ATP_SEND_TRACE("ATP/GSM : RING_OFF -> RING_ON (Voice) "
							,RV_TRACE_LEVEL_DEBUG_LOW); 
						break;
					}

				/* Not used */
				default:
					{
						atp_ring_type = ATP_NO_RING_TYPE;
						ATP_SEND_TRACE("ATP/GSM : RING_OFF -> RING_ON (Meaningless) "
							,RV_TRACE_LEVEL_DEBUG_LOW); 
						break;
					}
			} // End of switch

			/* Get the pointer on the port structure */
			if(atp_get_port(atp_gsm_sw_id,gsm_port_nb,&port_p,&sender_sw_nb) != RV_OK) 
			{
				atp_error_switch(ATP_ERROR_FAILED_TO_HANDLE_SIGNAL,ATP_PARAM_ERROR,NULL);
				return; /* This port does not exist */
			}
			if (atp_ring_type & port_p->port_info[(~sender_sw_nb)].ring_type)
			{
				new_signal |= ATP_RI_1;
				mask |= ATP_RI_UNMASK;
			}
		}
	}
	else
	{
		if ( (old_signal & ATP_RI_UNMASK) == ATP_RI_1) // RING is OFF and was previously ON
		{
			T_ATP_RING_TYPE atp_ring_type;
			T_ATP_SW_NB sender_sw_nb;
			T_ATP_PORT_STRUCT * port_p;

			switch (ring_type_1)
			{
				/* Transparent data */
				case BTI_AT_RING_Async:
					{
						atp_ring_type = ATP_DATA_RING_TYPE;
						ATP_SEND_TRACE("ATP/GSM : RING_ON -> RING_OFF (Transparent data) "
							,RV_TRACE_LEVEL_DEBUG_LOW); 
						break;
					}

				/* Non transparent data */
				case BTI_AT_RING_RelAsync:
					{
						atp_ring_type = ATP_DATA_RING_TYPE;
						ATP_SEND_TRACE("ATP/GSM : RING_ON -> RING_OFF (Non-transparent data) "
							,RV_TRACE_LEVEL_DEBUG_LOW); 
						break;
					}

				/* Fax */
				case BTI_AT_RING_Fax:
					{
						atp_ring_type = ATP_FAX_RING_TYPE;
						ATP_SEND_TRACE("ATP/GSM : RING_ON -> RING_OFF (Fax) "
							,RV_TRACE_LEVEL_DEBUG_LOW); 
						break;
					}

				/* Voice */
				case BTI_AT_RING_Voice:
					{
						atp_ring_type = ATP_VOICE_RING_TYPE;
						ATP_SEND_TRACE("ATP/GSM : RING_ON -> RING_OFF (Voice) "
							,RV_TRACE_LEVEL_DEBUG_LOW); 
						break;
					}

				/* Not used */
				default:
					{
						atp_ring_type = ATP_NO_RING_TYPE;
						ATP_SEND_TRACE("ATP/GSM : RING_ON -> RING_OFF (Meaningless) "
							,RV_TRACE_LEVEL_DEBUG_LOW); 
						break;
					}
			} // End of switch
			
			
			/* Get the pointer on the port structure */
			if(atp_get_port(atp_gsm_sw_id,gsm_port_nb,&port_p,&sender_sw_nb) != RV_OK) 
			{
				atp_error_switch(ATP_ERROR_FAILED_TO_HANDLE_SIGNAL,ATP_PARAM_ERROR,NULL);
				return; /* This port does not exist */
			}
			
			if (atp_ring_type & port_p->port_info[(~sender_sw_nb)].ring_type)
			{
				new_signal |= ATP_RI_0;
				mask |= ATP_RI_UNMASK;
			}			
			
			
		}
	}
	
	if ( (dce_signal & BTI_AT_DCD_MASK) == BTI_AT_DCD_ON) // DCD is ON
	{
		if ( (old_signal & ATP_DCD_UNMASK) == ATP_DCD_0) // DCD is ON and was previously OFF 
		{
			new_signal |= ATP_DCD_1;
			mask |= ATP_DCD_UNMASK;
			ATP_SEND_TRACE("ATP/GSM : DCD_OFF -> DCD_ON  ",
				RV_TRACE_LEVEL_DEBUG_LOW); 
		}
	}
	else
	{
		if ( (old_signal & ATP_DCD_UNMASK) == ATP_DCD_1) // DCD is OFF and was previously ON
		{
			new_signal |= ATP_DCD_0;
			mask |= ATP_DCD_UNMASK;
			ATP_SEND_TRACE("ATP/GSM : DCD_ON -> DCD_OFF  ",
				RV_TRACE_LEVEL_DEBUG_LOW); 
		}
	}
	if (mask != 0x00)
	{
		atp_set_signal(atp_gsm_sw_id,gsm_port_nb,new_signal,mask);
	}
}



/******************************************************************************
* Function name: atp_gsm_init_port
*
* Description : This function initialise the variable related to a port
*				 
*				
*
*
* Return     :  RV_OK
*
* History			: 0.1 (10-Jully-2000) 
*
******************************************************************************/
T_RV_RET atp_gsm_init_port(T_ATP_GSM_PORT_STRUCT * port_p)
{
	port_p->cmd_status = CMD_NOT_PENDING;
	port_p->gsm_tx_data_left = 0;
	port_p->atp_tx_data_activity = ATP_NOT_ACTIVE; 
	port_p->bt_max_payload = temp_bt_max_payload;
	return RV_OK;
}


/******************************************************************************
* Function name: atp_gsm_get_new_port_nb
*
* Description : Provide a new available port number if possible. Otherwise, return
*				error
*				
*
*
* Return     :  RV_OK
*
* History			: 0.1 (10-Jully-2000) 
*
******************************************************************************/
T_RV_RET atp_gsm_get_new_port_nb(UINT8 * port_nb)
{
	UINT8 i;
	
	for(i=0;i<ATP_MAX_NB_OF_PORT_SUPPORTED_BY_GSM;i++)
	{
		if (port_array[i] == NULL)
		{
			*port_nb = i;
			return RV_OK;
		}
	}
	*port_nb = 0xFF;
	return RV_NOT_SUPPORTED;
}