diff chipsetsw/services/atp/atp_cmd.c @ 0:509db1a7b7b8

initial import: leo2moko-r1
author Space Falcon <falcon@ivan.Harhan.ORG>
date Mon, 01 Jun 2015 03:24:05 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/chipsetsw/services/atp/atp_cmd.c	Mon Jun 01 03:24:05 2015 +0000
@@ -0,0 +1,2638 @@
+/********************************************************************************
+ *
+ * File Name : atp_cmd.c
+ *
+ * Functions handling the command translation between txt and command
+ * (and vice-versa)
+ *
+ * (C) Texas Instruments, all rights reserved
+ *
+ * Version number   : 0.1 - 03-03-2000
+ *
+ * History          : 0.1 - Created by E. Baissus
+ *                    0.2 - Reviewed : More generic AT commands handling and
+ *                                     copy optimization (especially on L2CAP
+ *                                     buffers)
+ *                    0.3 - '+CME ERROR' and '+CMS ERROR' support
+ *
+ * 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_api.h"
+#include "atp/atp_i.h"
+#include "atp/atp_config.h"
+#include "atp/atp_cmd.h"
+#include "rvm/rvm_use_id_list.h"
+#include <string.h>
+
+#ifdef BLUETOOTH
+#include "l2cap_data_hdlr.h"	/* For L2CAP data handling.                     */
+#endif
+
+/********************************************************************************
+* Function name	: dtoa
+*
+* Description   : Convert the digits of the given decimal value to a character 
+*				  string
+*
+* Parameters    : decimal = decimal value to be converted
+*                 ascii_p = string result
+*
+* Return        : Digit number
+*
+* Note          : digit and remainder declared as volatile to avoid bugs due to
+*				  optimization.
+*
+* History       : 0.1 (25-August-2000) - Created
+*
+*********************************************************************************/
+UINT8 dtoa (UINT16         decimal,
+			T_ATP_TXT_CMD  ascii_p)
+{
+    /* Declare local variables.                                                 */
+	T_ATP_TXT_CMD    str_p     = ascii_p;
+	volatile UINT8   digit     = 0x00;
+	volatile UINT16  remainder = decimal;
+
+/***************************** dtoa function begins *****************************/
+
+	/* Check to see if the string result is non-null.                           */
+	if (str_p == NULL)
+	{
+		return (0x00);
+	}
+
+	/* Convert the fifth digit: remainder = [65535,9999[.                       */
+	for (digit = 0x00;
+		 remainder > 9999;
+		 remainder -= 10000,
+		 digit++)
+	{
+	}
+	if (digit > 0x00)
+	{
+		*str_p++ = (INT8) ('0' + digit);
+	}
+
+	/* Convert the fourth digit: remainder = [9xxx,999[.                        */
+	for (digit = 0x00;
+		 remainder > 999;
+		 remainder -= 1000,
+		 digit++)
+	{
+	}
+	if ((digit > 0x00) || (str_p != ascii_p))
+	{
+		*str_p++ = (INT8) ('0' + digit);
+	}
+
+	/* Convert the third digit: remainder = [9xx,99[.                           */
+	for (digit = 0x00;
+		 remainder > 99;
+		 remainder -= 100,
+		 digit++)
+	{
+	}
+	if ((digit > 0x00) || (str_p != ascii_p))
+	{
+		*str_p++ = (INT8) ('0' + digit);
+	}
+
+	/* Convert the second digit: remainder = [9x,9[.                            */
+	for (digit = 0x00;
+		 remainder > 9;
+		 remainder -= 10,
+		 digit++)
+	{
+	}
+	if ((digit > 0x00) || (str_p != ascii_p))
+	{
+		*str_p++ = (INT8) ('0' + digit);
+	}
+
+	/* Convert the last digit: remainder = [9,0].                               */
+	*str_p++ = (INT8) ('0' + remainder);
+
+	/* Return the length of the string.                                         */
+	return ((UINT8) (str_p - ascii_p));
+
+} /**************************** End of dtoa function ****************************/
+
+
+/********************************************************************************
+* Function name : atp_cmd_init_dce_info
+*
+* Description   : Initialize the whole of the information stored in the 'DCE 
+*                 information' structure
+*
+* Parameter     : dce_info_p = pointer on the DCE information
+*
+* Return        : RV_OK
+*
+* History       : 0.1 (28-August-2000) - Created
+*
+*********************************************************************************/
+T_ATP_RET atp_cmd_init_dce_info (T_ATP_DCE_INFO  *dce_info_p)
+{
+    /* Declare a local variable.                                                */
+	UINT8  count = 0;
+
+/********************* atp_cmd_init_dce_info function begins ********************/
+
+	rvf_send_trace ("ATP : DCE information initialized ",
+					34,
+					NULL_PARAM,
+					RV_TRACE_LEVEL_DEBUG_LOW,
+					ATP_USE_ID);
+
+	/* Define the default command line termination character (See ITU-T         */
+	/* Recommendation V.250 ter page 21).                                       */
+	dce_info_p->cr_character = ATP_CR_CHARACTER;
+
+	/* Define the default response formatting character (See ITU-T              */
+	/* Recommendation V.250 ter page 22).                                       */
+	dce_info_p->lf_character = ATP_LF_CHARACTER;
+
+	/* Define the default command line editing character (See ITU-T             */
+	/* Recommendation V.250 ter page 22).                                       */
+	dce_info_p->bs_character = ATP_BS_CHARACTER;
+
+	/* Define the escape sequence (See ITU-T Recommendation V.250 ter page 24). */
+	memcpy ((void *) (dce_info_p->escape_sequence),
+			ATP_ESCAPE_SEQUENCE,
+			MAX_NB_OF_CHARACTER_FOR_END_SEQUENCE);
+
+	/* Define the command echo (See ITU-T Recommendation V.250 ter page 23).    */
+	dce_info_p->echo_mode = ECHO_OFF;
+
+	/* Define the result code suppression (See ITU-T Recommendation V.250 ter   */
+	/* page 23).                                                                */
+	dce_info_p->result_code_mode = RESULT_CODE_ON;
+
+	/* Define the DCE response format (See ITU-T Recommendation V.250 ter page  */
+	/* 24).                                                                     */
+	dce_info_p->verbose_mode = ATP_VERBOSE_1;
+
+	/* Initialize the masks associated with the commands executed by the ATP.   */
+	memset ((void *) (dce_info_p->dce_mask),
+			0x00,
+			sizeof (T_ATP_DCE_MASK));
+
+	/* Initialize pointers on temporary buffers containing the escape sequence. */
+	for (count = 0;
+		 count < MAX_NB_OF_CHARACTER_FOR_END_SEQUENCE;
+		 count++)
+	{
+
+		/* Initialize the pointer on a temporary data buffer containing part of */
+		/* the assumed escape sequence.                                         */
+		dce_info_p->escape_sequence_tmp_buffer_p[count] = NULL;
+
+		/* Initialize the number of data included in buffer hereinabove.        */
+		dce_info_p->length_of_escape_sequence_tmp_buffer_p[count] = 0;
+	}
+	dce_info_p->nb_plus_received = 0;
+	return (RV_OK);
+
+} /******************** End of atp_cmd_init_dce_info function *******************/
+
+
+/********************************************************************************
+* Function name : atp_get_custom_info_from_txt
+*
+* Description   : Etract custom information from a text string
+*
+* Parameters    : text_pp = string containing the command (0-terminated)
+*                 cmd_format = related structure
+*                 mb_id = memory bank used to get the custom command information
+*                         buffer
+*                 termination_char = termination character ('\x00' or <CR>)
+*
+* Return        : cmd_info_pp and RV_OK if the command is found,
+*                 RV_NOT_SUPPORTED
+*
+* Note          : Space characters are ignored and may be used freely for formatting
+*                 purposes, unless they are embedded in numeric or string constants
+*                 (See ITU-T Recommendation V.250 ter sections 5.4.2.1 or 5.4.2.2 on
+*                 pages 6 and 7). The DCE shall be capable of accepting at least 40
+*                 characters in the body.
+*
+* History       : 0.1 (29-August-2000) - Created
+*
+*********************************************************************************/
+T_ATP_RET atp_get_custom_info_from_txt (T_ATP_TXT_CMD     *text_pp,
+										T_ATP_CMD_FORMAT  cmd_format,
+										T_RVF_MB_ID       mb_id,
+										T_ATP_CMD         **cmd_info_pp,
+										const char        termination_char)
+{
+
+/***************** atp_get_custom_info_from_txt function begins *****************/
+
+	switch (cmd_format)
+	{
+
+		/* Basic syntax command does not expect any <number>.                   */
+		case ATP_NO_PARAM:
+			{
+				*cmd_info_pp = NULL;
+				return (RV_OK);
+			}
+
+		/* Basic syntax command.                                                */
+		case ATP_BASIC_PARAM:
+			{
+
+				/* Allocate memory in order to store the <number> associated    */
+				/* with basic syntax commands. If insufficient resources        */
+				/* available, then report an internal memory error and abort.   */
+				if (rvf_get_buf (mb_id, \
+								 sizeof (T_ATP_BASIC_CMD), \
+								 (void **) cmd_info_pp) == RVF_RED)
+				{
+					atp_error (ATP_ERROR_TX_MB_RED);
+					return (RV_MEMORY_ERR);
+				}
+
+				/* Get the <number> of the basic syntax command (See ITU-T      */
+				/* Recommendation V.250 ter page 5).                            */
+				memset ((void *) (*cmd_info_pp),
+						0x00,
+						sizeof (T_ATP_BASIC_CMD));
+				ATP_GET_NUMBER (*text_pp,
+								&((*((T_ATP_BASIC_CMD **) cmd_info_pp))->number),
+								'0');
+				return (RV_OK);
+			}
+
+		/* Dial.                                                                */
+		case ATP_DIAL_PARAM:
+			{
+
+				/* Allocate memory in order to store the <dial_string>          */
+				/* associated with the dial. If insufficient resources          */
+				/* available, then report an internal memory error and abort.   */
+				if (rvf_get_buf (mb_id, \
+								 sizeof (T_ATP_DIAL), \
+								 (void **) cmd_info_pp) == RVF_RED)
+				{
+					atp_error (ATP_ERROR_TX_MB_RED);
+					return (RV_MEMORY_ERR);
+				}
+
+				/* Get the <dial_string> of the dial (See ITU-T Recommendation  */
+				/* V.250 ter page 31). All characters appearing on the same     */
+				/* command line after D are considered part of the call         */
+				/* addressing information to be signalled to the network, or    */
+				/* modifiers used to control the signalling process, up to a    */
+				/* semicolon character or the end of the command line. If the   */
+				/* <dial_string> is terminated by a semicolon, the DCE does not */
+				/* start the call origination procedure, but instead returns to */
+				/* command state after completion of the signalling of call     */
+				/* addressing information to the network.                       */
+				memset ((void *) (*cmd_info_pp),
+						0x00,
+						sizeof (T_ATP_DIAL));
+				ATP_GET_DIAL_STRING (*text_pp,
+									 (*((T_ATP_DIAL **) cmd_info_pp))->dial_string_p,
+									 &((*((T_ATP_DIAL **) cmd_info_pp))->dial_string_length),
+									 &((*((T_ATP_DIAL **) cmd_info_pp))->call_type),
+									 termination_char);
+				return (RV_OK);
+			}
+
+		/* S-parameter.                                                         */
+		case ATP_S_PARAM:
+			{
+
+				/* Allocate memory in order to store the <value> associated     */
+				/* with S-parameters. If insufficient resources available, then */
+				/* report an internal memory error and abort.                   */
+				if (rvf_get_buf (mb_id, \
+								 sizeof (T_ATP_S_PARAM), \
+								 (void **) cmd_info_pp) == RVF_RED)
+				{
+					atp_error (ATP_ERROR_TX_MB_RED);
+					return (RV_MEMORY_ERR);
+				}
+
+				/* Get the characters that immediately follow                   */
+				/* <parameter_number>. "=" is used to set the indicated         */
+				/* S-parameter to a new value (See ITU-T Recommendation V.250   */
+				/* ter page 5). Note that if no value is given, the S-parameter */
+				/* specified may be set to 0, or an ERROR result code issued    */
+				/* and the stored value left unchanged. "?" is used to read the */
+				/* current value of the indicated S-parameter (See ITU-T        */
+				/* Recommendation V.250 ter page 5).                            */
+				memset ((void *) (*cmd_info_pp),
+						0x00,
+						sizeof (T_ATP_S_PARAM));
+				ATP_GET_PARAMETER_VALUE (*text_pp,
+										 &((*((T_ATP_S_PARAM **) cmd_info_pp))->s_operator),
+										 &((*((T_ATP_S_PARAM **) cmd_info_pp))->value));
+				return (RV_OK);
+			}
+
+		/* Extended syntax command does not expect any <value>.                 */
+		case ATP_NO_EXTENDED_PARAM:
+			{
+
+				/* Allocate memory in order to store the <value> associated     */
+				/* with extended syntax commands. If insufficient resources     */
+				/* available, then report an internal memory error and abort.   */
+				if (rvf_get_buf (mb_id, \
+								 sizeof (T_ATP_NO_SUBPARAMETER), \
+								 (void **) cmd_info_pp) == RVF_RED)
+				{
+					atp_error (ATP_ERROR_TX_MB_RED);
+					return (RV_MEMORY_ERR);
+				}
+
+				/* Get the characters that immediately follow <name>. "=?" is   */
+				/* used to test whether the extended syntax command is          */
+				/* implemented in the DCE (See ITU-T Recommendation V.250 ter   */
+				/* page 9).                                                     */
+				memset ((void *) (*cmd_info_pp),
+						0x00,
+						sizeof (T_ATP_NO_SUBPARAMETER));
+				ATP_GET_OPERATOR (*text_pp,
+								  &((*((T_ATP_NO_SUBPARAMETER **) cmd_info_pp))->extended_operator));
+				return (RV_OK);
+			}
+
+		/* Extended syntax command whose subparameter is a numeric constant.    */
+		case ATP_SINGLE_EXTENDED_PARAM:
+			{
+
+				/* Allocate memory in order to store the <value> associated     */
+				/* with extended syntax commands. If insufficient resources     */
+				/* available, then report an internal memory error and abort.   */
+				if (rvf_get_buf (mb_id, \
+								 sizeof (T_ATP_SINGLE_SUBPARAMETER), \
+								 (void **) cmd_info_pp) == RVF_RED)
+				{
+					atp_error (ATP_ERROR_TX_MB_RED);
+					return (RV_MEMORY_ERR);
+				}
+
+				/* Get the characters that immediately follow <name>. "=" is    */
+				/* used to set the indicated extended syntax command to a new   */
+				/* value (See ITU-T Recommendation V.250 ter page 8). Note that */
+				/* if no value is given, the extended syntax command specified  */
+				/* may be set to 0. "?" is used to read the current value of    */
+				/* the indicated extended syntax command (See ITU-T             */
+				/* Recommendation V.250 ter page 9). "=?" is used to test       */
+				/* whether the extended syntax command is implemented in the    */
+				/* DCE.                                                         */
+				memset ((void *) (*cmd_info_pp),
+						0x00,
+						sizeof (T_ATP_SINGLE_SUBPARAMETER));
+				ATP_GET_VALUE (*text_pp,
+							   &((*((T_ATP_SINGLE_SUBPARAMETER **) cmd_info_pp))->extended_operator),
+							   &((*((T_ATP_SINGLE_SUBPARAMETER **) cmd_info_pp))->value),
+							   termination_char);
+				return (RV_OK);
+			}
+
+		/* Keypad control command.                                              */
+		case ATP_PLUS_CKPD_PARAM:
+			{
+
+				/* Allocate memory in order to store the <keys>,<time> and      */
+				/* <pause> associated with +CKPD extended syntax command. If    */
+				/* insufficient resources available, then report an internal    */
+				/* memory error and abort.                                      */
+				if (rvf_get_buf (mb_id, \
+								 sizeof (T_ATP_PLUS_CKPD), \
+								 (void **) cmd_info_pp) == RVF_RED)
+				{
+					atp_error (ATP_ERROR_TX_MB_RED);
+					return (RV_MEMORY_ERR);
+				}
+
+				/* Get the <keys>,<time> and <pause> of the keypad control      */
+				/* command. Note that <keys> shall consist of a string constant */
+				/* and <time> and <pause> shall consist of numeric constants in */
+				/* tenths of a second (See ETS 300 916 (GSM 07.07) Version      */
+				/* 5.8.1 page 62). "=?" is used to test whether the extended    */
+				/* syntax command is implemented in the DCE.                    */
+				memset ((void *) (*cmd_info_pp),
+						0x00,
+						sizeof (T_ATP_PLUS_CKPD));
+				ATP_GET_CKPD_PARAM (*text_pp,
+									(*((T_ATP_PLUS_CKPD **) cmd_info_pp)),
+									termination_char);
+				return (RV_OK);
+			}
+
+		/* AT command undefined or not supported for now.                       */
+		default:
+			{
+				break;
+			}
+	}
+	return (RV_NOT_SUPPORTED);
+
+} /**************** End of atp_get_custom_info_from_txt function ****************/
+
+
+/********************************************************************************
+* Function name : atp_translate_raw_data_to_cmd
+*
+* Description   : Translate raw data into an interpreted command
+*
+* Parameters    : dce_info_p = pointer on the port structure
+*                 text_p = raw data containing the command (0-terminated)
+*                 cmd_type = command type of the text
+*                 cmd_type_p = type of the interpreted command
+*                 cmd_nb_p = binary related code of the interpreted command
+*                 skip_prefix = indicate whether the prefix shall be skipped in
+*                               order to proceed the translation
+*                 mb_id = memory bank used to get the custom command information
+*                         buffer
+*                 cmd_info_pp = pointer on the custom command information structure
+*
+* Return        : RV_OK,
+*                 RV_NOT_SUPPORTED if the command is not recognized,
+*                 RV_INVALID_PARAMETER
+*
+* Note          : A command line is made up of three elements: the prefix, the body,
+*                 and the termination character. The command line prefix consists of
+*                 the characters "AT" or "at", or, to repeat the execution of the 
+*                 previous command line, the characters "A/" or "a/". The body is
+*                 made up of individual commands. Space characters are ignored and
+*                 may be used freely for formatting purposes, unless they are embedded
+*                 in numeric or string constants (See ITU-T Recommendation V.250 ter
+*                 sections 5.4.2.1 or 5.4.2.2 on pages 6 and 7). The termination
+*                 character may not appear in the body. The DCE shall be capable of
+*                 accepting at least 40 characters in the body. Note that the
+*                 termination character may be selected by a user option (parameter
+*                 S3), the default being CR.
+*
+* History       : 0.1 (25-August-2000) - Created
+*
+*********************************************************************************/
+T_ATP_RET atp_translate_raw_data_to_cmd (T_ATP_PORT_STRUCT  *port_p,
+										 T_ATP_TXT_CMD      *text_pp,
+										 T_ATP_CMD_TYPE     cmd_type,
+										 T_ATP_CMD_TYPE     *cmd_type_p,
+										 T_ATP_CMD_NB       *cmd_nb_p,
+										 T_RVF_MB_ID        mb_id,
+										 T_ATP_CMD          **cmd_info_pp)
+{
+	/* Declare a local variable.                                                */
+	BOOLEAN  equal = FALSE;
+
+/***************** atp_translate_raw_data_to_cmd function begins ****************/
+
+	/* Check to see if the text command line is valid.                          */
+	if ((text_pp == NULL) || (*text_pp == NULL))
+	{
+		return (RV_INVALID_PARAMETER);
+	}
+
+	/* Initialize information for AT commands do not expect any number or       */
+	/* value.                                                                   */
+	*cmd_info_pp = NULL;
+
+	/* DTE command lines (See ITU-T Recommendation V.250 ter page 4). By the    */
+	/* way, note that the prefix consists of the characters "AT" or "at".       */
+	if ((cmd_type == UNKNOWN) || (cmd_type == AT_CMD))
+	{
+
+		/* Declare a local block variable.                                      */
+		UINT8  prefix_len = 0x00;
+
+		/* Check to see whether the prefix shall be skipped in order to proceed */
+		/* the translation.                                                     */
+		if ((port_p == NULL) || ((port_p->cmd_info).status == NOT_STARTED))
+		{
+			prefix_len = ATP_AT_PREFIX_LEN;
+		}
+
+		/* If the prefix is either "AT" or "at", then the DCE shall proceed the */
+		/* command line body (See ITU-T Recommendation V.250 ter page 4).       */
+		ATP_MEM_I_CMP (ATP_AT_PREFIX,
+					   *text_pp,
+					   prefix_len,
+					   &equal);
+		if (equal == TRUE)
+		{
+
+			/* Declare local block variables.                                   */
+			const char  *cmd_p  = NULL;
+			UINT8       cmd_len = 0x00;
+			
+			for (*cmd_nb_p   = 0x00, \
+				 *cmd_type_p = AT_CMD, \
+				 equal       = FALSE, \
+				 *text_pp    += prefix_len;
+				 *cmd_nb_p < ATP_MAX_NB_OF_AT_COMMANDS;
+				 (*cmd_nb_p)++)
+			{
+
+				/* If needed, skip this empty entry.                            */
+				if (ATP_AT_INFO[*cmd_nb_p][ATP_AT_PARAM_COLUMN] == ATP_CMD_NOT_DEFINED)
+				{
+					continue;
+				}
+
+				/* Get the length of the remainder.                             */
+				cmd_len = (UINT8) (ATP_AT_INFO[*cmd_nb_p + 0x01][ATP_AT_OFFSET_COLUMN] - ATP_AT_INFO[*cmd_nb_p][ATP_AT_OFFSET_COLUMN]);
+				cmd_p   = &(ATP_AT_TXT_TABLE[ATP_AT_INFO[*cmd_nb_p][ATP_AT_OFFSET_COLUMN]]);
+				ATP_MEM_SP_I_CMP (cmd_p,
+								  *text_pp,
+								  &cmd_len,
+								  &equal);
+
+				/* If both AT commands match, then get the custom information.  */
+				if (equal == TRUE)
+				{
+					rvf_send_trace ("ATP : Translate an AT command from text to command ",
+									51,
+									NULL_PARAM,
+									RV_TRACE_LEVEL_DEBUG_LOW,
+									ATP_USE_ID);
+					*text_pp += cmd_len;
+					(void) atp_get_custom_info_from_txt (text_pp,
+														 ATP_AT_INFO[*cmd_nb_p][ATP_AT_PARAM_COLUMN],
+														 mb_id,
+														 cmd_info_pp,
+														 (const char) ((port_p == NULL) ? ('\x00') : ((port_p->dce_info_p)->cr_character)));
+					return (RV_OK);
+				}
+			}
+			return (RV_NOT_SUPPORTED);
+		}
+	}
+
+	/* DCE responses (See ITU-T Recommendation V.250 ter page 10).              */
+	if ((cmd_type == UNKNOWN) || (cmd_type == RESULT_CODE) || \
+		(cmd_type == UNSOLICITED_RESULT))
+	{
+
+		/* Declare local block variables.                                       */
+		const char  *result_code_p  = NULL;
+		UINT8       header_len      = 0x00;
+		UINT8       result_code_len = 0x00;
+
+		/* If verbose responses are enabled, check to see whether leading <CR>  */
+		/* and <LF> characters shall be skipped in order to proceed the         */
+		/* translation.                                                         */
+		if ((port_p != NULL) && ((port_p->dce_info_p)->verbose_mode == ATP_VERBOSE_1))
+		{
+			equal = TRUE;
+			equal &= ((*text_pp)[0x00] == (port_p->dce_info_p)->cr_character);
+			equal &= ((*text_pp)[0x01] == (port_p->dce_info_p)->lf_character);
+
+			/* If leading characters do not match <CR><LF> headers of           */
+			/* information responses, then abort (See ETS 300 916 (GSM 07.07)   */
+			/* Version 4.1 page 13).                                            */
+			if (equal == FALSE)
+			{
+				*cmd_type_p = UNKNOWN;
+				return (RV_NOT_SUPPORTED);
+			}
+			header_len = ATP_RESULT_CODE_HEADER_LEN;
+		}
+		for (*cmd_nb_p   = 0x00, \
+			 *cmd_type_p = RESULT_CODE, \
+			 *text_pp    += header_len;
+			 *cmd_nb_p < ATP_MAX_NB_OF_RESULT_CODES;
+			 (*cmd_nb_p)++)
+		{
+
+			/* If needed, skip this empty entry.                                */
+			if (ATP_RESULT_CODE_INFO[*cmd_nb_p][ATP_RESULT_PARAM_COLUMN] == ATP_RESULT_CODE_NOT_DEFINED)
+			{
+				continue;
+			}
+
+			/* If verbose responses are disabled, then get the length of the    */
+			/* result code from the dedicated list.                             */
+			if ((port_p != NULL) && ((port_p->dce_info_p)->verbose_mode == ATP_VERBOSE_0))
+			{
+				result_code_len = (UINT8) (ATP_RESULT_CODE_INFO[*cmd_nb_p + 0x01][ATP_RESULT_OFFSET_V0_COLUMN] - ATP_RESULT_CODE_INFO[*cmd_nb_p][ATP_RESULT_OFFSET_V0_COLUMN]);
+				result_code_p   = &(ATP_RESULT_CODE_TXT_TABLE_V0[ATP_RESULT_CODE_INFO[*cmd_nb_p][ATP_RESULT_OFFSET_V0_COLUMN]]);
+			}
+			else
+			{
+				result_code_len = (UINT8) (ATP_RESULT_CODE_INFO[*cmd_nb_p + 0x01][ATP_RESULT_OFFSET_V1_COLUMN] - ATP_RESULT_CODE_INFO[*cmd_nb_p][ATP_RESULT_OFFSET_V1_COLUMN]);
+				result_code_p   = &(ATP_RESULT_CODE_TXT_TABLE_V1[ATP_RESULT_CODE_INFO[*cmd_nb_p][ATP_RESULT_OFFSET_V1_COLUMN]]);
+			}
+			ATP_MEM_I_CMP (result_code_p,
+						   *text_pp,
+						   result_code_len,
+						   &equal);
+			if (equal == FALSE)
+			{
+				continue;
+			}
+			rvf_send_trace ("ATP : Translate a result from text to command ",
+							46,
+							NULL_PARAM,
+							RV_TRACE_LEVEL_DEBUG_LOW,
+							ATP_USE_ID);
+			*text_pp += result_code_len;
+			switch (ATP_RESULT_CODE_INFO[*cmd_nb_p][ATP_RESULT_PARAM_COLUMN])
+			{
+
+				/* Extended syntax result code.                                 */
+				case ATP_EXTENDED_RESULT_CODE:
+					{
+
+						/* Allocate memory in order to store the <value>        */
+						/* associated with extended syntax result codes. If     */
+						/* insufficient resources available, then report an     */
+						/* internal memory error and abort.                     */
+						if (rvf_get_buf (mb_id, \
+										 sizeof (T_ATP_SINGLE_RESULT_CODE_VALUE), \
+										 (void **) cmd_info_pp) == RVF_RED)
+						{
+							atp_error (ATP_ERROR_TX_MB_RED);
+							return (RV_MEMORY_ERR);
+						}
+
+						/* Get the value associated with the extended result    */
+						/* codes (See Headset Specification, Section 4.7.3).    */
+						memset ((void *) (*cmd_info_pp),
+								0x00,
+								sizeof (T_ATP_SINGLE_RESULT_CODE_VALUE));
+						ATP_GET_RESULT_CODE_VALUE (*text_pp,
+												   &((*((T_ATP_SINGLE_RESULT_CODE_VALUE **) cmd_info_pp))->value));
+						break;
+					}
+
+				/* +CME ERROR: <error> and +CMS ERROR: <error> result codes.    */
+				case ATP_PLUS_ERROR_RESULT_CODE:
+					{
+
+						/* Allocate memory in order to store the <error>        */
+						/* associated with +CME ERROR or +CMS ERROR result      */
+						/* codes. If insufficient resources available, then     */
+						/* report an internal memory error and abort.           */
+						if (rvf_get_buf (mb_id, \
+										 sizeof (T_ATP_PLUS_ERROR_RESULT_CODE), \
+										 (void **) cmd_info_pp) == RVF_RED)
+						{
+							atp_error (ATP_ERROR_TX_MB_RED);
+							return (RV_MEMORY_ERR);
+						}
+
+						/* Get the <error> associated with the +CME ERROR or    */
+						/* +CMS ERROR result codes.                             */
+						memset ((void *) (*cmd_info_pp),
+								0x00,
+								sizeof (T_ATP_PLUS_ERROR_RESULT_CODE));
+						ATP_PLUS_ERROR_STRING (*text_pp,
+											   ((T_ATP_PLUS_ERROR_RESULT_CODE *) (*cmd_info_pp))->error_p,
+											   &(((T_ATP_PLUS_ERROR_RESULT_CODE *) (*cmd_info_pp))->error_length),
+											   '\x00');
+						break;
+					}
+				default:
+					{
+
+						/* Check to see if any text is associated with the      */
+						/* CONNECT result code.                                 */
+						if (*cmd_nb_p == ATP_CONNECT_NB)
+						{
+
+							/* Declare a local block variable.                  */
+							UINT16  connect_text = 0x0000;
+
+							/* Get the <text> associated with the CONNECT       */
+							/* result codes (See ITU-T Recommendation V.250 ter */
+							/* page 11).                                        */
+							ATP_GET_CONNECT_TXT (*text_pp,
+												 &connect_text);
+
+							/* If no <text> is associated with the CONNECT      */
+							/* result code, then abort.                         */
+							if (connect_text == 0x0000)
+							{
+								break;
+							}
+
+							/* Otherwise, allocate memory in order to store the */
+							/* <text> associated with the CONNECT result code.  */
+							/* If insufficient resources available, then report */
+							/* an internal memory error and abort.              */
+							if (rvf_get_buf (mb_id, \
+											 sizeof (T_ATP_CONNECT_TXT_PARAM), \
+											 (void **) cmd_info_pp) == RVF_RED)
+							{
+								atp_error (ATP_ERROR_TX_MB_RED);
+								return (RV_MEMORY_ERR);
+							}
+
+							/* Return the <text> associated with the CONNECT    */
+							/* result code.                                     */
+							(*((T_ATP_CONNECT_TXT_PARAM **) cmd_info_pp))->value = connect_text;
+							*cmd_nb_p = ATP_CONNECT_TXT_NB;
+						}
+						break;
+					}
+			}
+			return (RV_OK);
+		}
+	}
+	*cmd_type_p = UNKNOWN;
+	return (RV_NOT_SUPPORTED);
+
+} /**************** End of atp_translate_raw_data_to_cmd function ***************/
+
+
+/********************************************************************************
+* Function name : atp_translate_txt_to_cmd
+*
+* Description   : Translate a text string into an interpreted command
+*
+* Parameters    : text_p = text string containing the command (0-terminated)
+*                 cmd_type = command type of the text
+*                 cmd_type_p = type of the interpreted command
+*                 cmd_nb_p = binary related code of the interpreted command
+*                 mb_id = memory bank used to get the custom command information
+*                         buffer
+*                 cmd_info_pp = pointer on the custom command information structure
+*
+* Return        : RV_OK,
+*                 RV_NOT_SUPPORTED if the command is not recognized,
+*                 RV_INVALID_PARAMETER
+*
+* History       : 0.1 (25-August-2000) - Created
+*
+*********************************************************************************/
+T_ATP_RET atp_translate_txt_to_cmd (T_ATP_TXT_CMD   text_p,
+									T_ATP_CMD_TYPE  cmd_type,
+									T_ATP_CMD_TYPE  *cmd_type_p,
+									T_ATP_CMD_NB    *cmd_nb_p,
+									T_RVF_MB_ID     mb_id,
+									T_ATP_CMD       **cmd_info_pp)
+{
+	/* Declare a local variable.                                                */
+	T_ATP_RET  ret_status = RV_OK;
+		
+/******************* atp_translate_txt_to_cmd function begins *******************/
+
+	ret_status = atp_translate_raw_data_to_cmd (NULL,
+												&text_p,
+												cmd_type,
+												cmd_type_p,
+												cmd_nb_p,
+												mb_id,
+												cmd_info_pp);
+	return (ret_status);
+
+} /****************** End of atp_translate_txt_to_cmd function ******************/
+
+
+/********************************************************************************
+* Function name : atp_interpret_raw_data
+*
+* Description   : Fetch and interpret (if applicable and DCE mode) a new command
+*                 from the raw data buffer stored available in port_structure
+*
+* Parameters    : port_p = pointer on the port structure
+*                 mb_id = memory bank which the text buffer should be counted on
+*                 cmd_type_p = found command type (if UNKNOWN, should check text
+*                              field)
+*                 cmd_nb_p = found command number
+*                 cmd_info_p = pointer on the custom command information structure
+*                 text_pp = result of interpretation: contain next command to be
+*                           sent by ATP in text format (0-terminated) or NULL if
+*                           no command to be sent
+*                 text_length_p = length of the text command, '\x00' not included
+*
+* Return        : RV_MEMORY_ERR in case 'memory bank' get RED,
+*                 RV_NOT_SUPPORTED if the buffer does not contain proper data,
+*                 RV_OK otherwise
+*
+* Note          : The first data that should be checked are:
+*                 (port_p->cmd_info).cmd_txt_p[(port_p->cmd_info).next_position]
+*                 if (port_p->cmd_info).status = NOT_STARTED, an 'AT' should be
+*                 found
+*                 if the function has processed all the chain, it should set state
+*                 to FINISHED
+*                 (port_p->cmd_info).next_position must be updated by the function
+*
+* History       : 0.1 (25-August-2000) - Created
+*
+*********************************************************************************/
+T_ATP_RET atp_interpret_raw_data (T_ATP_PORT_STRUCT	 *port_p,
+								  T_RVF_MB_ID        mb_id,
+								  T_ATP_CMD_TYPE     *cmd_type_p,
+								  T_ATP_CMD_NB       *cmd_nb_p,
+								  T_ATP_CMD          **cmd_info_pp,
+								  T_ATP_TXT_CMD      *text_pp,
+								  UINT16             *text_length_p)
+{
+	/* Declare local variables.                                                 */
+	T_ATP_RET      ret_status = RV_OK;
+	T_ATP_TXT_CMD  text_p     = NULL;
+
+/******************** atp_interpret_raw_data function begins ********************/
+
+	rvf_send_trace ("ATP : Interpret raw data ",
+					25,
+					NULL_PARAM,
+					RV_TRACE_LEVEL_DEBUG_LOW,
+					ATP_USE_ID);
+
+	*text_pp = NULL;
+
+	/* Interpret all AT commands or result codes.                               */
+	while (((port_p->cmd_info).status == NOT_STARTED) || \
+		   (((port_p->cmd_info).status == ON_GOING) && \
+		   ((port_p->cmd_info).cmd_txt_p[(port_p->cmd_info).next_position] != (port_p->dce_info_p)->cr_character) && \
+		   ((port_p->cmd_info).next_position < (port_p->cmd_info).cmd_txt_length)))
+	{
+		text_p     = &((port_p->cmd_info).cmd_txt_p[(port_p->cmd_info).next_position]);
+		ret_status = atp_translate_raw_data_to_cmd (port_p,
+													&text_p,
+													UNKNOWN,
+													cmd_type_p,
+													cmd_nb_p,
+													mb_id,
+													cmd_info_pp);
+		
+		/* If any memory error occurred, then abort.                            */
+		if (ret_status == RV_MEMORY_ERR)
+		{
+			return (RV_MEMORY_ERR);
+		}
+		
+		/* Backup the next character to be interpreted.                         */
+		(port_p->cmd_info).status        = ON_GOING;
+		(port_p->cmd_info).next_position = (UINT16) (text_p - (port_p->cmd_info).cmd_txt_p);
+		
+		/* Intrepret the extracted command.                                     */
+		switch (*cmd_type_p)
+		{
+			
+			/* Interpret the extracted AT command.                              */
+			case AT_CMD:
+				{
+
+					/* Interpret AT commands only if ATP is acting as a DCE.	*/
+					if (port_p->port_config != DCE_CONFIG)
+					{
+						break;
+					}
+
+					/* Set the result of interpretation to NULL.                */
+					*text_pp = NULL;
+					switch (*cmd_nb_p)
+					{
+						
+						/* Answer. Note that any additional commands that       */
+						/* appear after A on the same command line are ignored  */
+						/* (See ITU-T Recommendation V.250 ter page 35).        */
+						case ATP_ATA_NB:
+						
+						/* Dial. Note that all characters appearing on the same */
+						/* command line after D are considered part of the call */
+						/* addressing information to be signalled to the        */
+						/* network, or modifiers used to control the signalling */
+						/* process, up to a semicolon character or the end of   */
+						/* the command line (See ITU-T Recommendation V.250 ter */
+						/* page 31). Note also that the ITU-T Recommendation    */
+						/* V.250 ter does not describe DCE behaviour in some    */
+						/* situations. Thus, additional characters that appear  */
+						/* on the same command line after a semicolon that      */
+						/* terminates dial string are either ignored or         */
+						/* processed as commands (See ITU-T Recommendation      */
+						/* V.250 ter page 14). In our implementation, such      */
+						/* additional characters are ignored.                   */
+						case ATP_ATD_NB:
+						
+						/* Reset to default configuration. Note that any        */
+						/* additional commands that appear on the same command  */
+						/* line after Z are ignored (See ITU-T Recommendation   */
+						/* V.250 ter page  15).                                 */
+						case ATP_ATZ_NB:
+							{
+								(port_p->cmd_info).next_position = (port_p->cmd_info).cmd_txt_length;
+								break;
+							}
+						
+						/* Command echo.                                        */
+						case ATP_ATE_NB:
+							{
+								
+								/* Check to see if the specified value is valid */
+								/* (See ITU-T Recommendation V.250 ter page     */
+								/* 23).                                         */
+								if (((*((T_ATP_ATE_PARAM **) cmd_info_pp))->number != ECHO_OFF) && \
+									((*((T_ATP_ATE_PARAM **) cmd_info_pp))->number != ECHO_ON))
+								{
+									rvf_send_trace ("ATP : Command echo value invalid ",
+													33,
+													NULL_PARAM,
+													RV_TRACE_LEVEL_WARNING,
+													ATP_USE_ID);
+									rvf_free_buf (*cmd_info_pp);
+									*cmd_info_pp = NULL;
+									return (RV_NOT_SUPPORTED);
+								}
+								rvf_send_trace ("ATP : Command echo updated ",
+												27,
+												NULL_PARAM,
+												RV_TRACE_LEVEL_DEBUG_LOW,
+												ATP_USE_ID);
+								(port_p->dce_info_p)->echo_mode = (*((T_ATP_ATE_PARAM **) cmd_info_pp))->number;
+								*cmd_type_p                     = UNKNOWN;
+								rvf_free_buf (*cmd_info_pp);
+								*cmd_info_pp = NULL;
+								
+								/* Interpret the next AT command or result code */
+								/* to come.                                     */
+								continue;
+							}
+							
+						/* Result code suppression.                             */
+						case ATP_ATQ_NB:
+							{
+								
+								/* Check to see if the specified value is valid */
+								/* (See ITU-T Recommendation V.250 ter page     */
+								/* 23).                                         */
+								if (((*((T_ATP_ATQ_PARAM **) cmd_info_pp))->number != RESULT_CODE_ON) && \
+									((*((T_ATP_ATQ_PARAM **) cmd_info_pp))->number != RESULT_CODE_OFF))
+								{
+									rvf_send_trace ("ATP : Result code suppression value invalid ",
+													44,
+													NULL_PARAM,
+													RV_TRACE_LEVEL_WARNING,
+													ATP_USE_ID);
+									rvf_free_buf (*cmd_info_pp);
+									*cmd_info_pp = NULL;
+									return (RV_NOT_SUPPORTED);
+								}
+								rvf_send_trace ("ATP : Result code suppression updated ",
+												38,
+												NULL_PARAM,
+												RV_TRACE_LEVEL_DEBUG_LOW,
+												ATP_USE_ID);
+								(port_p->dce_info_p)->result_code_mode = (*((T_ATP_ATQ_PARAM **) cmd_info_pp))->number;
+								*cmd_type_p                            = UNKNOWN;
+								rvf_free_buf (*cmd_info_pp);
+								*cmd_info_pp = NULL;
+								
+								/* Interpret the next AT command or result code */
+								/* to come.                                     */
+								continue;
+							}
+							
+						/* DCE response format.                                 */
+						case ATP_ATV_NB:
+							{
+								
+								/* Check to see if the specified value is valid */
+								/* (See ITU-T Recommendation V.250 ter page     */
+								/* 24).                                         */
+								if (((*((T_ATP_ATV_PARAM **) cmd_info_pp))->number != ATP_VERBOSE_0) && \
+									((*((T_ATP_ATV_PARAM **) cmd_info_pp))->number != ATP_VERBOSE_1))
+								{
+									rvf_send_trace ("ATP : DCE response format value invalid ",
+													40,
+													NULL_PARAM,
+													RV_TRACE_LEVEL_WARNING,
+													ATP_USE_ID);
+									rvf_free_buf (*cmd_info_pp);
+									*cmd_info_pp = NULL;
+									return (RV_NOT_SUPPORTED);
+								}
+								rvf_send_trace ("ATP : DCE response format updated ",
+												34,
+												NULL_PARAM,
+												RV_TRACE_LEVEL_DEBUG_LOW,
+												ATP_USE_ID);
+								(port_p->dce_info_p)->verbose_mode = (*((T_ATP_ATV_PARAM **) cmd_info_pp))->number;
+								*cmd_type_p                        = UNKNOWN;
+								rvf_free_buf (*cmd_info_pp);
+								*cmd_info_pp = NULL;
+								
+								/* Interpret the next AT command or result code */
+								/* to come.                                     */
+								continue;
+							}
+							
+						/* Command line termination character.                  */
+						case ATP_ATS3_NB:
+							{
+								
+								/* Check to see if the specified value is valid */
+								/* (See ITU-T Recommendation V.250 ter pages 21 */
+								/* and 22).                                     */
+								if ((((*((T_ATP_ATS3_PARAM **) cmd_info_pp))->s_operator != READ_S_PARAM) && \
+									((*((T_ATP_ATS3_PARAM **) cmd_info_pp))->s_operator != SET_S_PARAM)) || \
+									((*((T_ATP_ATS3_PARAM **) cmd_info_pp))->value > 0x007F))
+								{
+									rvf_send_trace ("ATP : Command line termination character invalid ",
+													49,
+													NULL_PARAM,
+													RV_TRACE_LEVEL_WARNING,
+													ATP_USE_ID);
+									rvf_free_buf (*cmd_info_pp);
+									*cmd_info_pp = NULL;
+									return (RV_NOT_SUPPORTED);
+								}
+								rvf_send_trace ("ATP : Command line termination character updated ",
+												49,
+												NULL_PARAM,
+												RV_TRACE_LEVEL_DEBUG_LOW,
+												ATP_USE_ID);
+								
+								/* Check to see if the S-parameter is requested */
+								/* to be set to a new value.                    */
+								if ((*((T_ATP_ATS3_PARAM **) cmd_info_pp))->s_operator == SET_S_PARAM)
+								{
+									(port_p->dce_info_p)->cr_character = (char) ((*((T_ATP_ATS3_PARAM **) cmd_info_pp))->value);
+									*cmd_type_p                        = UNKNOWN;
+									rvf_free_buf (*cmd_info_pp);
+									*cmd_info_pp = NULL;
+									
+									/* Interpret the next AT command or result  */
+									/* code to come.                            */
+									continue;
+								}
+								break;
+							}
+							
+						/* Response formatting character.                       */
+						case ATP_ATS4_NB:
+							{
+								
+								/* Check to see if the specified value is valid */
+								/* (See ITU-T Recommendation V.250 ter page     */
+								/* 22).                                         */
+								if ((((*((T_ATP_ATS4_PARAM **) cmd_info_pp))->s_operator != READ_S_PARAM) && \
+									((*((T_ATP_ATS4_PARAM **) cmd_info_pp))->s_operator != SET_S_PARAM)) || \
+									((*((T_ATP_ATS4_PARAM **) cmd_info_pp))->value > 0x007F))
+								{
+									rvf_send_trace ("ATP : Response formatting character invalid ",
+													44,
+													NULL_PARAM,
+													RV_TRACE_LEVEL_WARNING,
+													ATP_USE_ID);
+									rvf_free_buf (*cmd_info_pp);
+									*cmd_info_pp = NULL;
+									return (RV_NOT_SUPPORTED);
+								}
+								rvf_send_trace ("ATP : Response formatting character updated ",
+												44,
+												NULL_PARAM,
+												RV_TRACE_LEVEL_DEBUG_LOW,
+												ATP_USE_ID);
+								
+								/* Check to see if the S-parameter is requested */
+								/* to be set to a new value.                    */
+								if ((*((T_ATP_ATS4_PARAM **) cmd_info_pp))->s_operator == SET_S_PARAM)
+								{
+									(port_p->dce_info_p)->lf_character = (char) ((*((T_ATP_ATS4_PARAM **) cmd_info_pp))->value);
+									*cmd_type_p                        = UNKNOWN;
+									rvf_free_buf (*cmd_info_pp);
+									*cmd_info_pp = NULL;
+									
+									/* Interpret the next AT command or result  */
+									/* code to come.                            */
+									continue;
+								}
+								break;
+							}
+							
+						/* Command line editing character.                      */
+						case ATP_ATS5_NB:
+							{
+								
+								/* Check to see if the specified value is valid */
+								/* (See ITU-T Recommendation V.250 ter page     */
+								/* 22).                                         */
+								if ((((*((T_ATP_ATS5_PARAM **) cmd_info_pp))->s_operator != READ_S_PARAM) && \
+									((*((T_ATP_ATS5_PARAM **) cmd_info_pp))->s_operator != SET_S_PARAM)) || \
+									((*((T_ATP_ATS5_PARAM **) cmd_info_pp))->value > 0x007F))
+								{
+									rvf_send_trace ("ATP : Command line editing character invalid ",
+													45,
+													NULL_PARAM,
+													RV_TRACE_LEVEL_WARNING,
+													ATP_USE_ID);
+									rvf_free_buf (*cmd_info_pp);
+									*cmd_info_pp = NULL;
+									return (RV_NOT_SUPPORTED);
+								}
+								rvf_send_trace ("ATP : Command line editing character updated ",
+												45,
+												NULL_PARAM,
+												RV_TRACE_LEVEL_DEBUG_LOW,
+												ATP_USE_ID);
+								
+								/* Check to see if the S-parameter is requested */
+								/* to be set to a new value.                    */
+								if ((*((T_ATP_ATS5_PARAM **) cmd_info_pp))->s_operator == SET_S_PARAM)
+								{
+									(port_p->dce_info_p)->bs_character = (char) ((*((T_ATP_ATS5_PARAM **) cmd_info_pp))->value);
+									*cmd_type_p                        = UNKNOWN;
+									rvf_free_buf (*cmd_info_pp);
+									*cmd_info_pp = NULL;
+									
+									/* Interpret the next AT command or result  */
+									/* code to come.                            */
+									continue;
+								}
+								break;
+							}
+
+						/* AT command not recognized.                           */
+						case ATP_MAX_NB_OF_AT_COMMANDS:
+							{
+
+								/* Get the length of the AT command to be       */
+								/* returned, '\x00' not included.               */
+								ATP_GET_UNKNOWN_AT_CMD_LEN (text_p,
+															text_length_p,
+															(port_p->dce_info_p)->cr_character);
+
+								/* Allocate memory in order to return the AT    */
+								/* command ('\x00' included). Note that the     */
+								/* prefix must be taken into account. If        */
+								/* insufficient resources available, then       */
+								/* report an internal memory error and abort.   */
+								if (rvf_get_buf (mb_id, \
+												 ATP_AT_PREFIX_LEN + *text_length_p + 0x0001, \
+												 (void **) text_pp) == RVF_RED)
+								{
+									atp_error (ATP_ERROR_TX_MB_RED);
+									ret_status = RV_MEMORY_ERR;
+									break;
+								}
+
+								/* Copy the prefix into the buffer (See ITU-T   */
+								/* Recommendation V.250 ter page 4).            */
+								memcpy ((void *) *text_pp,
+										ATP_AT_PREFIX,
+										ATP_AT_PREFIX_LEN);
+
+								/* Then, copy the command line body into the    */
+								/* buffer.                                      */
+								memcpy ((void *) &((*text_pp)[ATP_AT_PREFIX_LEN]),
+										(void *) text_p,
+										*text_length_p);
+								(*text_pp)[*text_length_p + ATP_AT_PREFIX_LEN] = '\x00';
+								text_p                                         += *text_length_p;
+								break;
+							}
+
+						/* Other recognized AT commands.                        */
+						default:
+							{
+								break;
+							}
+					}
+
+					/* If the extracted AT command is an extended syntax        */
+					/* command, then update the position of the next character  */
+					/* to be interpreted.                                       */
+					switch (ATP_AT_INFO[*cmd_nb_p][ATP_AT_PARAM_COLUMN])
+					{
+
+						/* AT command undefined or not supported for now.       */
+						case ATP_CMD_NOT_DEFINED:
+
+						/* Extended syntax command does not expect any <value>. */
+						case ATP_NO_EXTENDED_PARAM:
+
+						/* Extended syntax command whose subparameter is a      */
+						/* numeric constant.                                    */
+						case ATP_SINGLE_EXTENDED_PARAM:
+
+						/* Keypad control command.                              */
+						case ATP_PLUS_CKPD_PARAM:
+							{
+								text_p                           += ((*text_p == (port_p->dce_info_p)->cr_character) ? (0x0000) : (0x0001));
+								(port_p->cmd_info).next_position = (UINT16) (text_p - (port_p->cmd_info).cmd_txt_p);
+							}
+						default:
+							{
+								break;
+							}
+					}
+					break;
+				}
+
+			/* Return raw data as received.									    */
+			case UNKNOWN:
+				{
+
+					/* Get the length of raw data to be returned, '\x00' not    */
+					/* included.                                                */
+					ATP_GET_UNKNOWN_CMD_LEN (text_p,
+											 text_length_p,
+											 (port_p->dce_info_p)->cr_character);
+
+					/* Allocate memory in order to return raw data ('\x00'      */
+					/* included). If insufficient resources available, then     */
+					/* report an internal memory error and abort.               */
+					if (rvf_get_buf (mb_id, \
+									 *text_length_p + 0x0001, \
+									 (void **) text_pp) == RVF_RED)
+					{
+						atp_error (ATP_ERROR_TX_MB_RED);
+						ret_status = RV_MEMORY_ERR;
+						break;
+					}
+
+					/* Copy raw data into the buffer.                           */
+					memcpy ((void *) *text_pp,
+							(void *) text_p,
+							*text_length_p);
+					(*text_pp)[*text_length_p] = '\x00';
+					text_p                     += *text_length_p;
+
+					/* Backup the next character to be interpreted.             */
+					(port_p->cmd_info).next_position = (UINT16) (text_p - (port_p->cmd_info).cmd_txt_p);
+					break;
+				}
+
+			/* Else, result codes not supported.                                */
+			case RESULT_CODE:
+			case UNSOLICITED_RESULT:
+			default:
+				{
+					break;
+				}
+		}
+		break;
+	}
+
+	/* Then, check to see whether the interpretation is over.                   */
+	if (((port_p->cmd_info).cmd_txt_p[(port_p->cmd_info).next_position] == (port_p->dce_info_p)->cr_character) || \
+		((port_p->cmd_info).next_position >= (port_p->cmd_info).cmd_txt_length))
+	{
+		(port_p->cmd_info).status = FINISHED;
+	}
+	return (RV_OK);
+
+} /******************* End of atp_interpret_raw_data function *******************/
+
+
+/********************************************************************************
+* Function name	: atp_translate_cmd_to_txt
+*
+* Description   : Translate a command in interpreted format to text format. Buffer 
+*                 containing the command is assumed to be BTF buffer and is freed
+*                 by this function. Text buffer is a BTF buffer
+*
+* Parameters    : cmd_type = type of the command (AT_CMD, RESULT_CODE and 
+*                 UNSOLICITED_RESULT)
+*                 cmd_nb = binary related code
+*                 cmd_info_p = pointer on the custom command information structure
+*                 mb_id = memory bank used to get the text buffer
+*                 text_pp = pointer on the text chain (0-terminated)
+*                 text_length_p = length of the text chain, '\x00' not included
+*
+* Return        : RV_OK,
+*                 RV_NOT_SUPPORTED if the command is not recognized
+*
+* History       : 0.1 (25-August-2000) - Created
+*
+*********************************************************************************/
+T_ATP_RET atp_translate_cmd_to_txt (T_ATP_CMD_TYPE  cmd_type,
+									T_ATP_CMD_NB    cmd_nb,
+									T_ATP_CMD       *cmd_info_p,
+									T_RVF_MB_ID     mb_id,
+									T_ATP_TXT_CMD   *text_pp,
+									UINT16          *text_length_p)
+{
+    /* Declare local variables.                                                 */
+	const char  *table     = NULL;
+	UINT16      offset     = 0x0000;
+	T_ATP_RET   ret_status = RV_OK;
+	
+/******************* atp_translate_cmd_to_txt function begins *******************/
+
+	switch (cmd_type)
+	{
+
+		/* Translate AT commands into text.                                     */
+		case AT_CMD:
+			{
+				rvf_send_trace ("ATP : Translate an AT command into text ",
+								40,
+								NULL_PARAM,
+								RV_TRACE_LEVEL_DEBUG_LOW,
+								ATP_USE_ID);
+				table = ATP_AT_TXT_TABLE;
+
+				/* Get the related offset.                                      */
+				offset = ATP_AT_INFO[cmd_nb][ATP_AT_OFFSET_COLUMN];
+
+				/* Get the length of the AT command.                            */
+				*text_length_p = (UINT16) (ATP_AT_PREFIX_LEN + \
+										   ATP_AT_INFO[cmd_nb + 0x01][ATP_AT_OFFSET_COLUMN] - ATP_AT_INFO[cmd_nb][ATP_AT_OFFSET_COLUMN]);
+
+				/* Get the related structure.                                   */
+				switch (ATP_AT_INFO[cmd_nb][ATP_AT_PARAM_COLUMN])
+				{
+
+					/* Basic syntax command does not expect any <number>.       */
+					case ATP_NO_PARAM:
+						{
+
+							/* Create a buffer and copy text string into it     */
+							/* ('\x00' included). If insufficient resources     */
+							/* available, then report an internal memory error  */
+							/* and abort.                                       */
+							if (rvf_get_buf (mb_id, \
+											 *text_length_p + 0x0001, \
+											 (void **) text_pp) == RVF_RED)
+							{
+								atp_error (ATP_ERROR_TX_MB_RED);
+								ret_status = RV_MEMORY_ERR;
+								break;
+							}
+	
+							/* Copy the command line prefix into the buffer.    */
+							memcpy ((void *) (*text_pp),
+									ATP_AT_PREFIX,
+									ATP_AT_PREFIX_LEN);
+
+							/* Copy the text into the buffer.                   */
+							memcpy ((void *) &((*text_pp)[ATP_AT_PREFIX_LEN]),
+									(void *) &(table[offset]),
+									*text_length_p - ATP_AT_PREFIX_LEN);
+							(*text_pp)[*text_length_p] = '\x00';
+							break;
+						}
+
+					/* Basic syntax command.                                    */
+					case ATP_BASIC_PARAM:
+						{
+
+							/* Declare a local block variable.                  */
+							T_ATP_BASIC_CMD  *basic_cmd_param_p = (T_ATP_BASIC_CMD *) cmd_info_p;
+
+							/* Create a buffer and copy text string into it     */
+							/* ('\x00' included). If insufficient resources     */
+							/* available, then report an internal memory error  */
+							/* and abort.                                       */
+							if (rvf_get_buf (mb_id, \
+											 *text_length_p + MAX_BASIC_CMD_PARAM_LEN + 0x0001, \
+											 (void **) text_pp) == RVF_RED)
+							{
+								atp_error (ATP_ERROR_TX_MB_RED);
+								ret_status = RV_MEMORY_ERR;
+								break;
+							}
+	
+							/* Copy the command line prefix into the buffer.    */
+							memcpy ((void *) (*text_pp),
+									ATP_AT_PREFIX,
+									ATP_AT_PREFIX_LEN);
+
+							/* Copy the text into the buffer.                   */
+							memcpy ((void *) &((*text_pp)[ATP_AT_PREFIX_LEN]),
+									(void *) &(table[offset]),
+									*text_length_p - ATP_AT_PREFIX_LEN);
+
+							/* If needed, copy the buffer describing the        */
+							/* command in interpreted format and free it.       */
+							if (basic_cmd_param_p != NULL)
+							{
+								*text_length_p = (UINT16) (*text_length_p + \
+														   dtoa (basic_cmd_param_p->number,
+																 &((*text_pp)[*text_length_p])));
+							}
+							(*text_pp)[*text_length_p] = '\x00';
+							break;
+						}
+
+					/* Dial.                                                    */
+					case ATP_DIAL_PARAM:
+						{
+
+							/* Declare local block variables.                   */
+							UINT8       dial_param_length = 0x00;
+							UINT8       dial_semicolon    = DATA_CALL;
+							T_ATP_DIAL  *dial_param_p     = (T_ATP_DIAL *) cmd_info_p;
+
+							/* If needed, take the buffer describing the        */
+							/* command in interpreted format into account.      */
+							if (dial_param_p != NULL)
+							{
+								dial_param_length = dial_param_p->dial_string_length;
+								dial_semicolon    = (UINT8) (dial_param_p->call_type);
+							}
+
+							/* Create a buffer and copy text string into it     */
+							/* ('\x00' included). If insufficient resources     */
+							/* available, then report an internal memory error  */
+							/* and abort.                                       */
+							if (rvf_get_buf (mb_id, \
+											 *text_length_p + dial_param_length + dial_semicolon + 0x0001, \
+											 (void **) text_pp) == RVF_RED)
+							{
+								atp_error (ATP_ERROR_TX_MB_RED);
+								ret_status = RV_MEMORY_ERR;
+								break;
+							}
+	
+							/* Copy the command line prefix into the buffer.    */
+							memcpy ((void *) (*text_pp),
+									ATP_AT_PREFIX,
+									ATP_AT_PREFIX_LEN);
+
+							/* Copy the text into the buffer.                   */
+							memcpy ((void *) &((*text_pp)[ATP_AT_PREFIX_LEN]),
+									(void *) &(table[offset]),
+									*text_length_p - ATP_AT_PREFIX_LEN);
+
+							/* If needed, copy the buffer describing the        */
+							/* command in interpreted format and free it.       */
+							if (dial_param_p != NULL)
+							{
+								memcpy ((void *) &((*text_pp)[*text_length_p]),
+										(void *) (dial_param_p->dial_string_p),
+										dial_param_length);
+								if (dial_semicolon == VOICE_CALL)
+								{
+									(*text_pp)[*text_length_p + dial_param_length] = ';';
+								}
+								*text_length_p = (UINT16) (*text_length_p + \
+														   dial_param_length + dial_semicolon);
+							}
+							(*text_pp)[*text_length_p] = '\x00';
+							break;
+						}
+
+					/* S-parameter.                                             */
+					case ATP_S_PARAM:
+						{
+
+							/* Declare a local block variable.                  */
+							T_ATP_S_PARAM  *s_param_p = (T_ATP_S_PARAM *) cmd_info_p;
+
+							/* Create a buffer and copy text string into it     */
+							/* ('\x00' included). If insufficient resources     */
+							/* available, then report an internal memory error  */
+							/* and abort.                                       */
+							if (rvf_get_buf (mb_id, \
+											 *text_length_p + MAX_S_PARAM_LEN + 0x0001,
+											 (void **) text_pp) == RVF_RED)
+							{
+								atp_error (ATP_ERROR_TX_MB_RED);
+								ret_status = RV_MEMORY_ERR;
+								break;
+							}
+	
+							/* Copy the command line prefix into the buffer.    */
+							memcpy ((void *) (*text_pp),
+									ATP_AT_PREFIX,
+									ATP_AT_PREFIX_LEN);
+
+							/* Copy the text into the buffer.                   */
+							memcpy ((void *) &((*text_pp)[ATP_AT_PREFIX_LEN]),
+									(void *) &(table[offset]),
+									*text_length_p - ATP_AT_PREFIX_LEN);
+
+							/* If needed, copy the buffer describing the        */
+							/* command in interpreted format and free it.       */
+							if (s_param_p == NULL)
+							{
+								(*text_pp)[*text_length_p] = '\x00';
+								break;
+							}
+							switch (s_param_p->s_operator)
+							{
+
+								/* Parameter read command syntax.               */
+								case READ_S_PARAM:
+									{
+										(*text_pp)[(*text_length_p)++] = '?';
+										(*text_pp)[*text_length_p]     = '\x00';
+										break;
+									}
+
+								/* Parameter set command syntax.                */
+								case SET_S_PARAM:
+									{
+										(*text_pp)[(*text_length_p)++] = '=';
+										*text_length_p = (UINT16) (*text_length_p + \
+																   dtoa (s_param_p->value,
+																		 &((*text_pp)[*text_length_p])));
+										(*text_pp)[*text_length_p] = '\x00';
+										break;
+									}
+								default:
+									{
+										rvf_free_buf (*text_pp);
+										*text_pp   = NULL;
+										ret_status = RV_NOT_SUPPORTED;
+										break;
+									}
+							}
+							break;
+						}
+
+					/* Extended syntax command does not expect any <value>.     */
+					case ATP_NO_EXTENDED_PARAM:
+						{
+
+							/* Declare a local block variable.                  */
+							T_ATP_NO_SUBPARAMETER  *extended_cmd_param_p = (T_ATP_NO_SUBPARAMETER *) cmd_info_p;
+
+							/* Create a buffer and copy text string into it     */
+							/* ('\x00' included). If insufficient resources     */
+							/* available, then report an internal memory error  */
+							/* and abort.                                       */
+							if (rvf_get_buf (mb_id, \
+											 *text_length_p + MAX_NO_SUBPARAMETER_LEN + 0x0001, \
+											 (void **) text_pp) == RVF_RED)
+							{
+								atp_error (ATP_ERROR_TX_MB_RED);
+								ret_status = RV_MEMORY_ERR;
+								break;
+							}
+	
+							/* Copy the command line prefix into the buffer.    */
+							memcpy ((void *) (*text_pp),
+									ATP_AT_PREFIX,
+									ATP_AT_PREFIX_LEN);
+
+							/* Copy the text into the buffer.                   */
+							memcpy ((void *) &((*text_pp)[ATP_AT_PREFIX_LEN]),
+									(void *) &(table[offset]),
+									*text_length_p - ATP_AT_PREFIX_LEN);
+
+							/* If needed, copy the buffer describing the        */
+							/* command in interpreted format and free it.       */
+							if (extended_cmd_param_p == NULL)
+							{
+								(*text_pp)[*text_length_p] = '\x00';
+								break;
+							}
+							switch (extended_cmd_param_p->extended_operator)
+							{
+
+								/* No subparameter.                             */
+								case NO_SUBPARAMETER:
+									{
+										(*text_pp)[*text_length_p] = '\x00';
+										break;
+									}
+
+								/* Action test command syntax.                  */
+								case TEST_EXTENDED_CMD:
+									{
+										(*text_pp)[(*text_length_p)++] = '=';
+										(*text_pp)[(*text_length_p)++] = '?';
+										(*text_pp)[*text_length_p]     = '\x00';
+										break;
+									}
+								default:
+									{
+										rvf_free_buf (*text_pp);
+										*text_pp   = NULL;
+										ret_status = RV_NOT_SUPPORTED;
+										break;
+									}
+							}
+							break;
+						}
+
+					/* Extended syntax command whose subparameter is a numeric  */
+					/* constant.                                                */
+					case ATP_SINGLE_EXTENDED_PARAM:
+						{
+
+							/* Declare a local block variable.                  */
+							T_ATP_SINGLE_SUBPARAMETER  *extended_cmd_param_p = (T_ATP_SINGLE_SUBPARAMETER *) cmd_info_p;
+
+							/* Create a buffer and copy text string into it     */
+							/* ('\x00' included). If insufficient resources     */
+							/* available, then report an internal memory error  */
+							/* and abort.                                       */
+							if (rvf_get_buf (mb_id, \
+											 *text_length_p + MAX_SINGLE_SUBPARAMETER_LEN + 0x0001, \
+											 (void **) text_pp) == RVF_RED)
+							{
+								atp_error (ATP_ERROR_TX_MB_RED);
+								ret_status = RV_MEMORY_ERR;
+								break;
+							}
+	
+							/* Copy the command line prefix into the buffer.    */
+							memcpy ((void *) (*text_pp),
+									ATP_AT_PREFIX,
+									ATP_AT_PREFIX_LEN);
+
+							/* Copy the text into the buffer.                   */
+							memcpy ((void *) &((*text_pp)[ATP_AT_PREFIX_LEN]),
+									(void *) &(table[offset]),
+									*text_length_p - ATP_AT_PREFIX_LEN);
+
+							/* If needed, copy the buffer describing the        */
+							/* command in interpreted format and free it.       */
+							if (extended_cmd_param_p == NULL)
+							{
+								(*text_pp)[*text_length_p] = '\x00';
+								break;
+							}
+							switch (extended_cmd_param_p->extended_operator)
+							{
+
+								/* No subparameter.                             */
+								case NO_SUBPARAMETER:
+									{
+										(*text_pp)[*text_length_p] = '\x00';
+										break;
+									}
+
+								/* Action test command syntax.                  */
+								case TEST_EXTENDED_CMD:
+									{
+										(*text_pp)[(*text_length_p)++] = '=';
+									}
+
+								/* Parameter read command syntax.               */
+								case READ_EXTENDED_CMD:
+									{
+										(*text_pp)[(*text_length_p)++] = '?';
+										(*text_pp)[*text_length_p]     = '\x00';
+										break;
+									}
+
+								/* Parameter set command syntax.                */
+								case SET_EXTENDED_CMD:
+									{
+										(*text_pp)[(*text_length_p)++] = '=';
+										*text_length_p = (UINT16) (*text_length_p + \
+																   dtoa (extended_cmd_param_p->value,
+																		 &((*text_pp)[*text_length_p])));
+										(*text_pp)[*text_length_p] = '\x00';
+										break;
+									}
+								default:
+									{
+										rvf_free_buf (*text_pp);
+										*text_pp   = NULL;
+										ret_status = RV_NOT_SUPPORTED;
+										break;
+									}
+							}
+							break;
+						}
+
+					/* Keypad control command. Note that <keys> is a string of  */
+					/* characters representing keys (See See ETS 300 916 (GSM   */
+					/* 07.07) Version 5.8.1 page 62). Colon character followed  */
+					/* by one character can be used to indicate a manufacturer  */
+					/* specific key not listed here. All characters from a      */
+					/* semicolon character to the next single semicolon         */
+					/* character are treated as alpha entries and are not       */
+					/* converted to key equivalents. All semicolon characters   */
+					/* inside alpha entries should be duplicated in the DTE.    */
+					/* Pause characters "W" and "w" can be used to pause        */
+					/* between key pressings for a time specified by <pause>.   */
+					case ATP_PLUS_CKPD_PARAM:
+						{
+
+							/* Declare local block variables.                   */
+							UINT8            nb_keypressed = 0x00;
+							T_ATP_PLUS_CKPD  *ckpd_param_p = (T_ATP_PLUS_CKPD *) cmd_info_p;
+
+							/* Create a buffer and copy text string into it     */
+							/* ('\x00' included). If insufficient resources     */
+							/* available, then report an internal memory error  */
+							/* and abort.                                       */
+							if (rvf_get_buf (mb_id, \
+											 *text_length_p + MAX_CKPD_PARAM_LEN + 0x0001, \
+											 (void **) text_pp) == RVF_RED)
+							{
+								atp_error (ATP_ERROR_TX_MB_RED);
+								ret_status = RV_MEMORY_ERR;
+								break;
+							}
+
+							/* Copy the command line prefix into the buffer.    */
+							memcpy ((void *) (*text_pp),
+									ATP_AT_PREFIX,
+									ATP_AT_PREFIX_LEN);
+
+							/* Copy the text into the buffer.                   */
+							memcpy ((void *) &((*text_pp)[ATP_AT_PREFIX_LEN]),
+									(void *) &(table[offset]),
+									*text_length_p - ATP_AT_PREFIX_LEN);
+
+							/* If needed, copy the buffer describing the        */
+							/* command in interpreted format and free it.       */
+							if (ckpd_param_p == NULL)
+							{
+								(*text_pp)[*text_length_p] = '\x00';
+								break;
+							}
+							switch (ckpd_param_p->extended_operator)
+							{
+
+								/* Action test command syntax.                  */
+								case TEST_EXTENDED_CMD:
+									{
+										(*text_pp)[(*text_length_p)++] = '=';
+										(*text_pp)[(*text_length_p)++] = '?';
+										(*text_pp)[*text_length_p]     = '\x00';
+										break;
+									}
+
+								/* Parameter set command syntax.                */
+								case SET_EXTENDED_CMD:
+									{
+										(*text_pp)[(*text_length_p)++] = '=';
+										(*text_pp)[(*text_length_p)++] = '"';
+
+										/* Store each keypressed into the       */
+										/* buffer.                              */
+										for (nb_keypressed = 0x00;
+											 nb_keypressed < ckpd_param_p->nb_keys;
+											 nb_keypressed++)
+										{
+											(*text_pp)[(*text_length_p)++] = ';';
+											*text_length_p = (UINT16) (*text_length_p + \
+																	   dtoa (ckpd_param_p->keys[nb_keypressed],
+																			 &((*text_pp)[*text_length_p])));
+											(*text_pp)[(*text_length_p)++] = ';';
+										}
+										(*text_pp)[(*text_length_p)++] = '"';
+
+										/* Store <time> subparameter into the   */
+										/* buffer.                              */
+										(*text_pp)[(*text_length_p)++] = ',';
+										if ((ckpd_param_p->pause != DEFAULT_TIME) || \
+											(ckpd_param_p->pause != TIME_DO_NOT_CARE))
+										{
+											*text_length_p = (UINT16) (*text_length_p + \
+																	   dtoa (ckpd_param_p->time,
+																			 &((*text_pp)[*text_length_p])));
+										}
+
+										/* Store <pause> subparameter into the  */
+										/* buffer.                              */
+										(*text_pp)[(*text_length_p)++] = ',';
+										if ((ckpd_param_p->pause != DEFAULT_PAUSE) || \
+											(ckpd_param_p->pause != PAUSE_DO_NOT_CARE))
+										{
+											*text_length_p = (UINT16) (*text_length_p + \
+																	   dtoa (ckpd_param_p->pause,
+																			 &((*text_pp)[*text_length_p])));
+										}
+										(*text_pp)[*text_length_p] = '\x00';
+										break;
+									}
+								default:
+									{
+										rvf_free_buf (*text_pp);
+										*text_pp   = NULL;
+										ret_status = RV_NOT_SUPPORTED;
+										break;
+									}
+							}
+							break;
+						}
+					default:
+						{
+							rvf_send_trace ("ATP : Received an unknown command ",
+											34,
+											NULL_PARAM,
+											RV_TRACE_LEVEL_WARNING,
+											ATP_USE_ID);
+							*text_pp   = NULL;
+							ret_status = RV_NOT_SUPPORTED;
+							break;
+						}
+				}
+				break;
+			}
+
+		/* Translate DCE responses into text (See ITU-T Recommendation V.250    */
+		/* ter page 10).                                                        */
+		case RESULT_CODE:
+		case UNSOLICITED_RESULT:
+			{
+				rvf_send_trace ("ATP : Translate a result into text ",
+								35,
+								NULL_PARAM,
+								RV_TRACE_LEVEL_DEBUG_LOW,
+								ATP_USE_ID);
+				table = ATP_RESULT_CODE_TXT_TABLE_V1;
+
+				/* Get the related offset.                                      */
+				offset = ATP_RESULT_CODE_INFO[cmd_nb][ATP_RESULT_OFFSET_V1_COLUMN];
+
+				/* Get the length of the result code.                           */
+				*text_length_p = (UINT16) (ATP_RESULT_CODE_INFO[cmd_nb + 0x01][ATP_RESULT_OFFSET_V1_COLUMN] - ATP_RESULT_CODE_INFO[cmd_nb][ATP_RESULT_OFFSET_V1_COLUMN]);
+
+				/* Get the related structure.                                   */
+				switch (ATP_RESULT_CODE_INFO[cmd_nb][ATP_RESULT_PARAM_COLUMN])
+				{
+
+					/* Basic syntax result code.                                */
+					case ATP_BASIC_RESULT_CODE:
+						{
+
+							/* Create a buffer and copy text string into it     */
+							/* ('\x00' included). If insufficient resources     */
+							/* available, then report an internal memory error  */
+							/* and abort.                                       */
+							if (rvf_get_buf (mb_id, \
+											 *text_length_p + 0x0001, \
+											 (void **) text_pp) == RVF_RED)
+							{
+								atp_error (ATP_ERROR_TX_MB_RED);
+								ret_status = RV_MEMORY_ERR;
+								break;
+							}
+
+							/* Copy text into the buffer.                       */
+							memcpy ((void *) (*text_pp),
+									(void *) &(table[offset]),
+									*text_length_p);
+							(*text_pp)[*text_length_p] = '\x00';
+							break;
+						}
+
+					/* Extended syntax result code.                             */
+					case ATP_EXTENDED_RESULT_CODE:
+						{
+
+							/* Declare a local block variable.                  */
+							T_ATP_SINGLE_RESULT_CODE_VALUE  *result_code_param_p = (T_ATP_SINGLE_RESULT_CODE_VALUE *) cmd_info_p;
+
+							/* Create a buffer and copy text string into it     */
+							/* ('=' and '\x00' included). If insufficient       */
+							/* resources available, then report an internal     */
+							/* memory error and abort.                          */
+							if (rvf_get_buf (mb_id, \
+											 *text_length_p + MAX_SINGLE_RESULT_CODE_VALUE_LEN + 0x0002, \
+											 (void **) text_pp) == RVF_RED)
+							{
+								atp_error (ATP_ERROR_TX_MB_RED);
+								ret_status = RV_MEMORY_ERR;
+								break;
+							}
+
+							/* Copy text into the buffer.                       */
+							memcpy ((void *) (*text_pp),
+									(void *) &(table[offset]),
+									*text_length_p);
+
+							/* If needed, copy the buffer describing the        */
+							/* command in interpreted format and free it.       */
+							if (result_code_param_p != NULL)
+							{
+								(*text_pp)[(*text_length_p)++] = '=';
+								*text_length_p = (UINT16) (*text_length_p + \
+														   dtoa (result_code_param_p->value,
+																 &((*text_pp)[*text_length_p])));
+							}
+							(*text_pp)[*text_length_p] = '\x00';
+							break;
+						}
+
+					/* CONNECT <text> result code.                              */
+					case ATP_CONNECT_TXT_PARAM:
+						{
+
+							/* Declare a local block variable.                  */
+							T_ATP_CONNECT_TXT_PARAM  *connect_txt_param_p = (T_ATP_CONNECT_TXT_PARAM *) cmd_info_p;
+
+							/* Create a buffer and copy text string into it     */
+							/* (' ' and '\x00' included). If insufficient       */
+							/* resources available, then report an internal     */
+							/* memory error and abort.                          */
+							if (rvf_get_buf (mb_id, \
+											 *text_length_p + MAX_CONNECT_TXT_LEN + 0x0002, \
+											 (void **) text_pp) == RVF_RED)
+							{
+								atp_error (ATP_ERROR_TX_MB_RED);
+								ret_status = RV_MEMORY_ERR;
+								break;
+							}
+
+							/* Copy text into the buffer.                       */
+							memcpy ((void *) (*text_pp),
+									(void *) &(table[offset]),
+									*text_length_p);
+
+							/* If needed, copy the buffer describing the        */
+							/* command in interpreted format and free it.       */
+							if (connect_txt_param_p != NULL)
+							{
+								(*text_pp)[(*text_length_p)++] = ' ';
+								*text_length_p = (UINT16) (*text_length_p + \
+														   dtoa (connect_txt_param_p->value,
+																 &((*text_pp)[*text_length_p])));
+							}
+							(*text_pp)[*text_length_p] = '\x00';
+							break;
+						}
+
+					/* +CME ERROR: <error> and +CMS ERROR: <error> result       */
+					/* codes.                                                   */
+					case ATP_PLUS_ERROR_RESULT_CODE:
+						{
+
+							/* Declare local block variables.                   */
+							UINT8                         error_length              = 0x00;
+							T_ATP_PLUS_ERROR_RESULT_CODE  *plus_error_result_code_p = cmd_info_p;
+
+							/* If needed, take the buffer describing the        */
+							/* command in interpreted format into account.      */
+							if (plus_error_result_code_p != NULL)
+							{
+								error_length = plus_error_result_code_p->error_length;
+							}
+
+							/* Create a buffer and copy text string into it     */
+							/* (' ' and '\x00' included). If insufficient       */
+							/* resources available, then report an internal     */
+							/* memory error and abort.                          */
+							if (rvf_get_buf (mb_id, \
+											 *text_length_p + error_length + 0x0002, \
+											 (void **) text_pp) == RVF_RED)
+							{
+								atp_error (ATP_ERROR_TX_MB_RED);
+								ret_status = RV_MEMORY_ERR;
+								break;
+							}
+	
+							/* Copy the command line prefix into the buffer.    */
+							memcpy ((void *) (*text_pp),
+									ATP_AT_PREFIX,
+									ATP_AT_PREFIX_LEN);
+
+							/* Copy the text into the buffer.                   */
+							memcpy ((void *) &((*text_pp)[ATP_AT_PREFIX_LEN]),
+									(void *) &(table[offset]),
+									*text_length_p - ATP_AT_PREFIX_LEN);
+
+							/* If needed, copy the buffer describing the        */
+							/* command in interpreted format and free it.       */
+							if (plus_error_result_code_p != NULL)
+							{
+								(*text_pp)[(*text_length_p)++] = ' ';
+								memcpy ((void *) &((*text_pp)[*text_length_p]),
+										(void *) (plus_error_result_code_p->error_p),
+										error_length);
+								*text_length_p = (UINT16) (*text_length_p + \
+														   error_length);
+							}
+							(*text_pp)[*text_length_p] = '\x00';
+							break;
+						}
+					default:
+						{
+							rvf_send_trace ("ATP : Received an unknown command ",
+											34,
+											NULL_PARAM,
+											RV_TRACE_LEVEL_WARNING,
+											ATP_USE_ID);
+							*text_pp   = NULL;
+							ret_status = RV_NOT_SUPPORTED;
+							break;
+						}
+				}
+				break;
+			}
+		default:
+			{
+				rvf_send_trace ("ATP : Received an unknown command ",
+								34,
+								NULL_PARAM,
+								RV_TRACE_LEVEL_WARNING,
+								ATP_USE_ID);
+				*text_pp   = NULL;
+				ret_status = RV_NOT_SUPPORTED;
+				break;
+			}
+	}
+
+	/* If needed, free the buffer describing the command in interpreted format. */
+	if (cmd_info_p != NULL)
+	{
+		rvf_free_buf (cmd_info_p);
+		cmd_info_p = NULL;
+	}
+	return (ret_status);
+
+} /****************** End of atp_translate_cmd_to_txt function ******************/
+
+
+/********************************************************************************
+* Function name : atp_copy_buffer
+* 
+* Description   : Copy 'data size' bytes of 'in buffer' to 'out buffer'
+*
+* Parameters    : in_buffer_p = buffer to copy from
+*                 out_buffer_p = new buffer
+*                 data_size = number of bytes to be copied
+*
+* Return        : RV_OK
+*
+* History       : 0.1 (05-May-2000) - Created
+*
+*********************************************************************************/
+T_ATP_RET atp_copy_buffer (UINT8   *in_buffer_p,
+						   UINT8   *out_buffer_p,
+						   UINT32  data_size)
+{
+
+/************************ atp_copy_buffer function begins ***********************/
+
+	memcpy ((void *) out_buffer_p,
+			(void *) in_buffer_p,
+			data_size);
+  	return (RV_OK);
+
+} /*********************** End of atp_copy_buffer function **********************/
+
+
+/********************************************************************************
+* Function name : atp_create_data_buffer_from_cmd
+* 
+* Description   : create a data buffer based on port features and on the command 
+*                 which is interpreted or in text format
+*
+* Parameters    : cmd_mode = interpreted or text
+*                 header = header size
+*                 trailer = trailer size
+*                 dce_info_p = pointer on the DCE information
+*                 mb_id = memory bank used to get the data buffer
+*                 cmd_type = type of the command
+*                 cmd_nb = related binary code of the command (not used if TXT
+*                          format)
+*                 text_p = pointer on the text string (0-terminated) (not used
+*                          if INTERPRETED format)
+*                 cmd_info_p = pointer on the custom command information structure
+*                              (not used if TXT format)
+*                 buffer_pp = pointer on the data buffer generated by the function
+*                 length_p = length of the data buffer
+*
+* Return        : RV_OK,
+*                 RV_NOT_SUPPORTED if the command is not recognized
+*
+* History       : 0.1 (01-March-2000) - Created
+*
+*********************************************************************************/
+T_ATP_RET atp_create_data_buffer_from_cmd (T_ATP_CMD_MODE  cmd_mode,
+										   UINT16          header,
+										   UINT16          trailer,
+										   T_ATP_DCE_INFO  *dce_info_p,
+										   T_RVF_MB_ID     mb_id,
+										   T_ATP_CMD_TYPE  cmd_type,
+										   T_ATP_CMD_NB    cmd_nb,
+										   T_ATP_TXT_CMD   text_p,
+										   T_ATP_CMD       *cmd_info_p,
+										   T_ATP_BUFFER    *buffer_pp,
+										   UINT16          *length_p)
+{
+    /* Declare local variables.                                                 */
+	UINT16         txt_length   = 0x0000;
+	T_ATP_BUFFER   atp_buffer_p = NULL;
+	T_ATP_TXT_CMD  text_cmd_p   = NULL;
+	
+/**************** atp_create_data_buffer_from_cmd function begins ***************/
+
+	/* Need to have the command type provided.                                  */
+	if (cmd_type == UNKNOWN)
+	{
+		return (RV_NOT_SUPPORTED);
+	}
+
+	/* Get text version of the AT command and point on it via text_cmd_p. If    */
+	/* the command has been provided already in text format, then...            */
+	if (cmd_mode == TXT_MODE)
+	{
+		text_cmd_p = text_p;
+
+		/* The length does not include '\x00'.                                  */
+		txt_length = (UINT16) (strlen (text_cmd_p));
+	}
+	else
+	{
+
+		/* Declare a local block variable.                                      */
+		T_ATP_RET  ret_status = RV_OK;
+
+		/* Translate the command into text.                                     */
+		ret_status = atp_translate_cmd_to_txt (cmd_type,
+											   cmd_nb,
+											   cmd_info_p,
+											   mb_id,
+											   &text_cmd_p,
+											   &txt_length);
+
+		/* If any error occurred, then abort.                                   */
+		if (ret_status != RV_OK)
+		{
+			return (RV_NOT_SUPPORTED);
+		}
+	}
+
+	/* Create real buffer to send for a AT Command.                             */
+	switch (dce_info_p->verbose_mode)
+	{
+
+		/* Verbose responses enabled.                                           */
+		case ATP_VERBOSE_0:
+			{
+				switch (cmd_type)
+				{
+
+					/* DCE responses (See ITU-T Recommendation V.250 ter page   */
+					/* 10).                                                     */
+					case RESULT_CODE:
+					case UNSOLICITED_RESULT:
+						{
+							*length_p = (UINT16) (trailer + header + 0x0002);
+
+							/* Create buffer and copy text string into it. If   */
+							/* insufficient resources available, then report an */
+							/* internal memory error and abort.                 */
+							if (rvf_get_buf (mb_id, \
+											 *length_p, \
+											 (void **) buffer_pp) == RVF_RED)
+							{
+								*length_p = 0x0000;
+								atp_error (ATP_ERROR_TX_MB_RED);
+								return (RV_MEMORY_ERR);
+							}
+							atp_buffer_p = *buffer_pp;
+
+							/* Add code.                                        */
+							atp_buffer_p[header] = (char) (cmd_nb + '0');
+
+							/* Add special characters.                          */
+							atp_buffer_p[header + 0x0001] = dce_info_p->cr_character;
+
+							/* Release text buffer.                             */
+							rvf_free_buf (text_cmd_p);
+							return (RV_OK);
+						}
+					case PRELIMINARY_RESULT_CODE:
+						{
+
+							/* Add 2 special characters <CR> and <LF>.          */
+							*length_p = (UINT16) (trailer + header + txt_length + 0x0002);
+			
+							/* Create buffer and copy text string into it. If   */
+							/* insufficient resources available, then report an */
+							/* internal memory error and abort.                 */
+							if (rvf_get_buf (mb_id, \
+											 *length_p, \
+											 (void **) buffer_pp) == RVF_RED)
+							{
+								*length_p = 0x0000;
+								atp_error (ATP_ERROR_TX_MB_RED);
+								return (RV_MEMORY_ERR);
+							}
+							atp_buffer_p = *buffer_pp;
+
+							/* Copy text into the buffer.                       */
+							memcpy ((void *) (atp_buffer_p + header),
+									(void *) text_cmd_p,
+									txt_length);
+
+							/* Add special characters.                          */
+							atp_buffer_p[header + txt_length]          = dce_info_p->cr_character;
+							atp_buffer_p[header + txt_length + 0x0001] = dce_info_p->lf_character;
+
+							/* Release text buffer.                             */
+							rvf_free_buf (text_cmd_p);
+							return (RV_OK);
+						}
+					default:
+						{
+							break;
+						}
+				}
+			}
+
+		/* Verbose responses disabled.                                          */
+		case ATP_VERBOSE_1:
+			{
+				switch (cmd_type)
+				{
+
+					/* DTE command lines (See ITU-T Recommendation V.250 ter    */
+					/* page 4).                                                 */
+					case AT_CMD:
+						{
+
+							/* The buffer contains AT command and <CR>          */
+							/* character.                                       */
+							*length_p = (UINT16) (trailer + header + txt_length + 0x0001);
+
+							/* Create buffer and copy text string into it. If   */
+							/* insufficient resources available, then report an */
+							/* internal memory error and abort.                 */
+							if (rvf_get_buf (mb_id, \
+											 *length_p, \
+											 (void **) buffer_pp) == RVF_RED)
+							{
+								*length_p = 0x0000;
+								atp_error (ATP_ERROR_TX_MB_RED);
+								return (RV_MEMORY_ERR);
+							}
+							atp_buffer_p = *buffer_pp;
+
+							/* Copy text into the buffer.                       */
+							memcpy ((void *) (atp_buffer_p + header),
+									(void *) text_cmd_p,
+									txt_length);
+
+							/* Add special characters.                          */
+							atp_buffer_p[header + txt_length] = dce_info_p->cr_character;
+
+							/* Release text buffer.                             */
+							rvf_free_buf (text_cmd_p);
+							return (RV_OK);
+						}
+
+					/* DCE responses (See ITU-T Recommendation V.250 ter page   */
+					/* 10).                                                     */
+					case RESULT_CODE:
+					case UNSOLICITED_RESULT:
+					case PRELIMINARY_RESULT_CODE:
+						{
+
+							/* Add 4 special characters <CR> and <LF> (twice).  */
+							*length_p = (UINT16) (trailer + header + txt_length + 0x0004);
+			
+							/* Create buffer and copy text string into it. If   */
+							/* insufficient resources available, then report an */
+							/* internal memory error and abort.                 */
+							if (rvf_get_buf (mb_id, \
+											 *length_p, \
+											 (void **) buffer_pp) == RVF_RED)
+							{
+								*length_p = 0x0000;
+								atp_error (ATP_ERROR_TX_MB_RED);
+								return (RV_MEMORY_ERR);
+							}
+							atp_buffer_p = *buffer_pp;
+
+							/* Copy text into the buffer.                       */
+							memcpy ((void *) (atp_buffer_p + header + 0x0002),
+									(void *) text_cmd_p,
+									txt_length);
+
+							/* Add special characters.                          */
+							atp_buffer_p[header]                       = dce_info_p->cr_character;
+							atp_buffer_p[header + 0x0001]              = dce_info_p->lf_character;
+							atp_buffer_p[header + txt_length + 0x0002] = dce_info_p->cr_character;
+							atp_buffer_p[header + txt_length + 0x0003] = dce_info_p->lf_character;
+
+							/* Release text buffer.                             */
+							rvf_free_buf (text_cmd_p);
+							return (RV_OK);
+						}
+					default:
+						{
+							rvf_send_trace ("ATP : Tried to create a buffer for an unknown command ",
+											54,
+											NULL_PARAM,
+											RV_TRACE_LEVEL_WARNING,
+											ATP_USE_ID);
+							*length_p  = 0x0000;
+							*buffer_pp = NULL;
+							break;
+						}
+				}
+				break;
+			}
+		default:
+			{
+				rvf_send_trace ("ATP : Verbose mode invalid ",
+								27,
+								NULL_PARAM,
+								RV_TRACE_LEVEL_WARNING,
+								ATP_USE_ID);
+				*length_p  = 0x0000;
+				*buffer_pp = NULL;
+				break;
+			}
+	}
+	return (RV_NOT_SUPPORTED);
+
+} /*************** End of atp_create_data_buffer_from_cmd function **************/
+
+
+/********************************************************************************
+* Function name : atp_copy_buffer_from_l2cap
+*
+* Description   : Check the text command
+*
+* Parameters    : l2cap_buffer_p = type is L2CAP_ACL_DATA
+*                 copy_buffer_p = pointer on the buffer to copy data in 
+*                 buffer_length = data length to read
+*
+* Return        : RV_OK if it fits
+*
+* Note          : l2cap_buffer_p is not freed by this function !
+*
+* History       : 0.1 (21-March-2000) - Created
+*
+*********************************************************************************/
+T_ATP_RET atp_copy_buffer_from_l2cap (void    *l2cap_buffer_p,
+									  void    *copy_buffer_p,
+									  UINT32  buffer_length,
+									  UINT32  offset)
+{
+
+#ifdef BLUETOOTH
+
+	/* Declare local variables.                                                 */
+	UINT16            nb_byte    = 0x0000;
+	T_RECV_DATA_ADDR  acl_data_p = {NULL, \
+									NULL};
+	
+/****************** atp_copy_buffer_from_l2cap function begins ******************/
+
+	rvf_send_trace ("ATP : Translate L2CAP buffer into a ATP buffer ",
+					47,
+					NULL_PARAM,
+					RV_TRACE_LEVEL_DEBUG_LOW,
+					ATP_USE_ID);
+	l2cap_read_next_uint ((T_L2CAP_ACL_DATA *) l2cap_buffer_p,
+						  sizeof (UINT8),
+						  ((UINT8 *) copy_buffer_p),
+						  &acl_data_p,
+						  (UINT8) offset);
+	for (nb_byte = 1;
+		 nb_byte < buffer_length;
+		 nb_byte++)
+	{
+		l2cap_read_next_uint ((T_L2CAP_ACL_DATA *) l2cap_buffer_p,
+							  sizeof (UINT8),
+							  ((UINT8 *) copy_buffer_p) + nb_byte,
+							  &acl_data_p,
+							  0x0000);
+	}
+	return (RV_OK);
+#else
+	rvf_send_trace ("ATP : Tried to read buffer in L2CAP format whereas Bluetooth is not enabled ",
+					76,
+					NULL_PARAM,
+					RV_TRACE_LEVEL_WARNING,
+					ATP_USE_ID);
+	return (RV_NOT_SUPPORTED);
+#endif
+	
+} /***************** End of atp_copy_buffer_from_l2cap function *****************/
+
+
+/********************************************************************************
+* Function name : atp_free_l2cap_buffer
+*
+* Description   : Release a L2CAP buffer
+*
+* Parameter     : l2cap_buffer_p = type is L2CAP_ACL_DATA
+*
+* Return        : RV_OK if free is OK
+*
+* History       : 0.1 (19-Dec-2001) - Created
+*
+*********************************************************************************/
+T_ATP_RET atp_free_l2cap_buffer (UINT8  *atp_buffer_p)
+{
+	
+/********************* atp_free_l2cap_buffer function begins ********************/
+
+#ifdef BLUETOOTH
+	return ((T_ATP_RET) (l2cap_free_data ((T_L2CAP_ACL_DATA *) atp_buffer_p)));
+#else
+	rvf_send_trace ("ATP : Tried to read buffer in L2CAP format whereas Bluetooth is not enabled ",
+					76,
+					NULL_PARAM,
+					RV_TRACE_LEVEL_WARNING,
+					ATP_USE_ID);
+	return (RV_NOT_SUPPORTED);
+#endif
+
+} /******************** End of atp_free_l2cap_buffer function *******************/
+
+
+/********************************************************************************
+* Function name : atp_escape_sequence_process
+*
+* Description   : This function is used to detect the escape sequence in the data
+*                 flow. This function should not be called if the port is not
+*                 configured in DCE mode. The escape sequence should start in a new
+*                 packet and the last character of the exit sequence should be the
+*                 last character of a packet. Note that each data buffer checked
+*                 that may be part of the escape sequence is temporarily stored so
+*                 that it can be sent to the SWE later on in case it was the escape
+*                 sequence.
+*
+* Parameters	: port_p = structure of the port
+*                 atp_buffer_p = pointer on the buffer received by ATP (can be a 
+*                 NORMAL data packet or a SEGMENTED data packet)
+*                 data_length = number of payload data in the packet pointed by
+*                 atp_buffer_p
+*                 packet_mode = indicates the mode of the data packet (NORMAL or
+*                 SEGMENTED)
+*
+* Return        : ATP_ESCAPE_SEQUENCE_SUCCESS,
+*                 ATP_ESCAPE_SEQUENCE_FAILED otherwise
+*
+* History       : 0.1 (06-Feb-2001) - Created
+*
+*********************************************************************************/
+T_ATP_ESCAPE_SEQUENCE_STATUS atp_escape_sequence_process (T_ATP_PORT_STRUCT  *port_p,
+														  UINT8              *atp_buffer_p,
+														  UINT32             data_length,
+														  T_ATP_PACKET_MODE  packet_mode)
+{
+	/* Declare local variables.                                                 */
+	UINT8  count   = 0;
+	UINT8  data_sequence[MAX_NB_OF_CHARACTER_FOR_END_SEQUENCE];
+	
+/****************** atp_escape_sequence_process function begins *****************/
+
+	/* Check the sequence. Indeed, there are data after the last character of   */
+	/* the escape sequence.                                                     */
+	if (((port_p->dce_info_p)->nb_plus_received + data_length) > MAX_NB_OF_CHARACTER_FOR_END_SEQUENCE)
+	{
+		return (ATP_ESCAPE_SEQUENCE_FAILED);
+	}
+
+	/* Get data from the buffer.                                                */
+	if (packet_mode == SEGMENTED_PACKET)
+	{
+		atp_copy_buffer_from_l2cap (atp_buffer_p,
+									data_sequence,
+									data_length,
+									0);
+	}
+	else
+	{
+		memcpy (data_sequence,
+				atp_buffer_p,
+				data_length);
+	}
+
+	/* Check every character.                                                   */
+	for (count = 0;
+		 count < data_length;
+		 count++)
+	{
+		if (data_sequence[count] != (port_p->dce_info_p)->escape_sequence[count + (port_p->dce_info_p)->nb_plus_received])
+		{
+			return (ATP_ESCAPE_SEQUENCE_FAILED);
+		}
+	}
+
+	/* Keep temporarily the pointer on the buffer.                              */
+	for (count = 0;
+		 (port_p->dce_info_p)->escape_sequence_tmp_buffer_p[count] != NULL;
+		 count++);
+	(port_p->dce_info_p)->escape_sequence_tmp_buffer_p[count]           = atp_buffer_p;
+	(port_p->dce_info_p)->length_of_escape_sequence_tmp_buffer_p[count]	= (UINT8) data_length;
+	if (((port_p->dce_info_p)->nb_plus_received + data_length) !=  MAX_NB_OF_CHARACTER_FOR_END_SEQUENCE)
+	{
+		(port_p->dce_info_p)->nb_plus_received = (UINT8) ((port_p->dce_info_p)->nb_plus_received + data_length);		
+		return (ATP_ESCAPE_SEQUENCE_WAIT);
+	}
+
+	/* Otherwise, all characters have been found.                               */
+	return (ATP_ESCAPE_SEQUENCE_SUCCESS);
+
+} /***************** End of atp_escape_sequence_process function ****************/
+
+  
+/********************************************************************************
+* Function name : atp_pipe_extra_character
+*
+* Description   : This function is called when it has been found that the escape
+*                 sequence search has failed and when other SWE is in copy mode.
+*                 In this case, data that has been received and that have not been
+*                 sent to the other SWE because we thought they may contain the
+*                 escape sequence must finally be sent.
+*                 For this reason, all the buffer to sent has been previously stored
+*                 in a temporary buffer called dce_info_p->escape_sequence_tmp_buffer_p.
+*                 This function pipes all this buffer into the data pipe of the SWE.
+*                 Note that such a complex mechanism is essentially due to the fact
+*                 that we may have to deal with L2CAP packet (SEGMENTED_MODE).
+*
+* Parameters    : port_p = pointer on the port structure
+*                 other_port_info_p = pointer on the port information structure of
+*                 the SWE which will receive the data.
+*
+* Return        : RV_OK
+*
+* History       : 0.1 (01-March-2000) - Created
+*
+*********************************************************************************/
+T_ATP_RET atp_pipe_extra_character (T_ATP_PORT_STRUCT      *port_p,
+									T_ATP_PORT_END_STRUCT  *other_port_info_p)
+{
+	/* Declare local variables.                                                 */
+	UINT8            count        = 0;
+	UINT8            nb_packet    = 0;
+	T_ATP_RX_PACKET  *rx_packet_p = NULL;
+	
+/******************* atp_pipe_extra_character function begins *******************/
+
+	for (nb_packet = 0;
+		 ((port_p->dce_info_p)->escape_sequence_tmp_buffer_p[nb_packet] != NULL) && \
+		 (nb_packet < MAX_NB_OF_CHARACTER_FOR_END_SEQUENCE);
+		 nb_packet++);
+	for (count = 0; count < nb_packet; count++)
+	{
+		if (rvf_get_buf (other_port_info_p->rx_mb, \
+						 sizeof (T_ATP_RX_PACKET), \
+						 (void **) &rx_packet_p) == RVF_RED)
+		{
+			atp_error_switch (ATP_ERROR_FAILED_TO_SEND_DATA,
+							  ATP_MEMORY_ERROR,NULL);
+			return (RV_MEMORY_ERR);
+		}
+		rx_packet_p->first_byte        = 0;
+		rx_packet_p->last_byte         = ((port_p->dce_info_p)->length_of_escape_sequence_tmp_buffer_p[count]) - 1;
+		rx_packet_p->atp_buffer_p      = (port_p->dce_info_p)->escape_sequence_tmp_buffer_p[count];
+		rx_packet_p->next_byte_to_read = rx_packet_p->first_byte;
+		rvf_enqueue (&(other_port_info_p->rx_queue),
+					 rx_packet_p);
+		other_port_info_p->rx_data_left += (port_p->dce_info_p)->length_of_escape_sequence_tmp_buffer_p[count];
+	}
+	return (RV_OK);
+
+} /****************** End of atp_pipe_extra_character function ******************/
+
+  
+/********************************************************************************
+* Function name : atp_reset_escape_sequence
+*
+* Description   : This function resets all internal values used by the algorithm
+*                 of escape sequence search (information stored in the dce_info_p
+*                 structure)
+*
+* Parameter     : port_p = pointer on the port structure
+*
+* Return        : RV_OK
+*
+* History       : 0.1 (01-March-2000) - Created
+*
+*********************************************************************************/
+T_ATP_RET atp_reset_escape_sequence (T_ATP_PORT_STRUCT  *port_p)
+{
+	/* Declare local variables.                                                 */
+	UINT8  count     = 0;
+	UINT8  *buffer_p = NULL;
+	
+/******************* atp_reset_escape_sequence function begins ******************/
+
+	(port_p->dce_info_p)->nb_plus_received = 0;
+	
+	/* Clear pointers on temporary buffer containing potentially escape         */
+	/* sequence.                                                                */
+	for (count = 0;
+		 count < MAX_NB_OF_CHARACTER_FOR_END_SEQUENCE;
+		 count++)
+	{
+		if ((buffer_p = (port_p->dce_info_p)->escape_sequence_tmp_buffer_p[count]) != NULL)
+		{
+
+#ifdef BLUETOOTH
+
+			/* Check if the buffer has been issued by SPP. Not very clean way to */
+			/* check what is the packet mode.                                    */
+			if ((strcmp ((char *) atp_sw_entity_table_p[(port_p->port_info[0]).sw_id]->sw_entity_name, \
+						 ATP_SPP_NAME) == 0) || \
+				(strcmp ((char *) atp_sw_entity_table_p[(port_p->port_info[1]).sw_id]->sw_entity_name, \
+						 ATP_SPP_NAME) == 0))
+			{
+
+				/* Mode is SEGMENTED PACKET.                                     */
+				l2cap_free_data ((T_L2CAP_ACL_DATA *) buffer_p);
+			}
+			else
+			{
+
+				/* Mode  is NORMAL_PACKET.                                       */
+				rvf_free_buf (buffer_p);
+			}
+#else
+			rvf_free_buf (buffer_p);
+#endif
+			(port_p->dce_info_p)->escape_sequence_tmp_buffer_p[count]           = NULL;
+			(port_p->dce_info_p)->length_of_escape_sequence_tmp_buffer_p[count] = 0;
+		}
+	}
+	return (RV_OK);
+
+} /****************** End of atp_reset_escape_sequence function ******************/