view src/cs/services/atp/atp_gsm_bt_api.c @ 0:945cf7f506b2

src/cs: chipsetsw import from tcs211-fcmodem binary blobs and LCD demo files have been excluded, all line endings are LF only
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 25 Sep 2016 22:50:11 +0000
parents
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;
}