diff chipsetsw/services/atp/atp_uart_handle_msg.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_uart_handle_msg.c	Mon Jun 01 03:24:05 2015 +0000
@@ -0,0 +1,1058 @@
+/********************************************************************************/
+/*                                                                              */
+/*    File Name:         atp_uart_handle_msg.c                                  */
+/*                                                                              */
+/*    Purpose:           This file contains the internal function related to    */
+/*                       the ATP-UART interface and used to handle incoming     */
+/*                       messages                                               */
+/*                                                                              */
+/*    Note:              None.                                                  */
+/*                                                                              */
+/*    Revision History:                                                         */
+/*       10/04/01        Pascal Pompei                                          */
+/*                          - Create.                                           */
+/*                                                                              */
+/* (C) Copyright 2001 by Texas Instruments Incorporated, All Rights Reserved.   */
+/*                                                                              */
+/********************************************************************************/
+#include "atp/atp_i.h"
+#include "atp/atp_uart_i.h"
+#include "rvm/rvm_use_id_list.h"
+
+
+/********************************************************************************/
+/*                                                                              */
+/*    Function Name:     atp_uart_handle_msg                                    */
+/*                                                                              */
+/*    Purpose:           This function handles incoming messages available from */
+/*                       the mailbox dedicated to the ATP-UART interface.       */
+/*                                                                              */
+/*    Input Parameters:  None.                                                  */
+/*                                                                              */
+/*    Output Parameters: None.                                                  */
+/*                                                                              */
+/*    Global Parameters: None.                                                  */
+/*                                                                              */
+/*    Notes:             The GSM protocol stack must be started first.          */
+/*                       Nevertheless, note that incoming data calls are not    */
+/*						 supported for now. Moreover, the AT Parser is alerted  */
+/*                       that the call is terminated by receiving an 'Ok' or a  */
+/*                       'No Carrier' final result code only. At last, the GSM  */
+/*                       protocol stack is initialized by invoking the          */
+/*                       following AT commands:                                 */
+/*                          ATE0      : Echo mode switched off,                 */
+/*                          AT+CFUN=1 : Set Phone Functionality (Full),         */
+/*                          AT+COPS=0 : Operator Selection.                     */
+/*                                                                              */
+/*    Revision History:                                                         */
+/*       10/04/01        Pascal Pompei                                          */
+/*                          - Create.                                           */
+/*                                                                              */
+/********************************************************************************/
+T_ATP_UART_ERROR_CODES atp_uart_handle_msg (void)
+{
+	/* Declare local variables.                                                 */
+	UINT16                event_pending          = 0x0000;
+	UINT32                in_buffer_size         = 0x00000000;
+	BOOLEAN               echo_mode_switched_off = FALSE;
+	BOOLEAN               error_occurred         = FALSE;
+	T_ATP_CALLBACK        return_path            = {0x00, \
+													NULL};
+	T_ATP_ENTITY_MODE     mode                   = {CMD_SUPPORT_ON, \
+													TXT_MODE, \
+													COPY_ON};
+	T_ATP_SW_ENTITY_NAME  name                   = ATP_GSM_NAME;
+
+/********************** atp_uart_handle_msg function begins *********************/
+
+	/* First, wait until the COM port is activated.                             */
+	while ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).com_port_handle == INVALID_HANDLE_VALUE)
+	{
+
+		/* Wait for the next event(s) of interest.                              */
+		event_pending = rvf_wait (ATP_UART_ALL_EVENT_FLAGS,
+								  0x00000000);
+
+		/* If an expected event occurred, then get the associated message from  */
+		/* the mailbox dedicated to the ATP-UART interface.                     */
+		if (event_pending & ATP_UART_EXPECTED_EVENT)
+		{
+
+			/* Declare a local block variable.                                  */
+			T_RV_HDR  *incoming_message_p = NULL;
+
+			/* Get the incoming message from the mailbox dedicated to the       */
+			/* ATP-UART interface.                                              */
+			incoming_message_p = (T_RV_HDR *) rvf_read_mbox (ATP_UART_MAILBOX);
+
+			/* Check whether the incoming message is valid.                     */
+			if (incoming_message_p == NULL)
+			{
+				ATP_UART_UNRECOVERABLE_ERROR (RVM_INTERNAL_ERR,
+											  "  ATP-UART (handle_msg). Invalid event occurred ");
+				return (RVM_INTERNAL_ERR);
+			}
+			switch (incoming_message_p->msg_id)
+			{
+
+				/* 'ATP-UART Open COM Port'.                                    */
+				case ATP_UART_OPEN_COM_PORT:
+					{
+
+						/* Declare a local block variable.                      */
+						UINT8  gsm_basic_init_p[] = {'A', 'T', 'E', '0', \
+													 ATP_CR_CHARACTER};
+
+						/* Open the COM port whose number and baud rate are     */
+						/* specified. If any error occurred, then call the      */
+						/* function used whenever any unrecoverable error       */
+						/* occurs and abort.                                    */
+						if (atp_uart_create_com_port ((unsigned char) (((T_ATP_UART_OPEN_COM_PORT *) (incoming_message_p))->com_port), \
+													  ((T_ATP_UART_OPEN_COM_PORT *) (incoming_message_p))->baud_rate) != RV_OK)
+						{
+							ATP_UART_UNRECOVERABLE_ERROR (RVM_INTERNAL_ERR,
+														  "  ATP-UART (handle_msg). Unable to activate the COM port ");
+							return (RVM_INTERNAL_ERR);
+						}
+						rvf_send_trace ("  ATP-UART (handle_msg). COM port properly opened ",
+										50,
+										NULL_PARAM,
+										RV_TRACE_LEVEL_DEBUG_LOW,
+										ATP_USE_ID);
+
+						/* Configure the GSM especially not to echo characters  */
+						/* during 'Command State' and 'Online Command State'.   */
+						/* If any error occurred, then call the function used   */
+						/* whenever any unrecoverable error occurs and abort.   */
+						if (atp_uart_write_com_port (gsm_basic_init_p, \
+													 sizeof (gsm_basic_init_p)) != RV_OK)
+						{
+							ATP_UART_UNRECOVERABLE_ERROR (RVM_INTERNAL_ERR,
+														  "  ATP-UART (handle_msg). GSM configuration failed ");
+							return (RVM_INTERNAL_ERR);
+						}
+						break;
+					}
+
+				/* Unexpected message.                                          */
+				default:
+					{
+						rvf_send_trace ("  ATP-UART (handle_msg). Unexpected message received ",
+										53,
+										incoming_message_p->msg_id,
+										RV_TRACE_LEVEL_WARNING,
+										ATP_USE_ID);
+						break;
+					}
+			}
+			(void) rvf_free_buf ((T_RVF_BUFFER *) (incoming_message_p));
+		}
+	}
+
+	/* Then, wait for the echo mode being switched off.                         */
+	while (echo_mode_switched_off == FALSE)
+	{
+
+		/* Wait for the next event(s) of interest.                              */
+		event_pending = rvf_wait (ATP_UART_ALL_EVENT_FLAGS,
+								  0x00000001);
+
+		/* If an expected event occurred, then get the associated message from  */
+		/* the mailbox dedicated to the ATP-UART interface.                     */
+		if (event_pending & ATP_UART_EXPECTED_EVENT)
+		{
+
+			/* Declare a local block variable.                                  */
+			T_RV_HDR  *incoming_message_p = NULL;
+
+			/* Get the incoming message from the mailbox dedicated to the       */
+			/* ATP-UART interface.                                              */
+			incoming_message_p = (T_RV_HDR *) rvf_read_mbox (ATP_UART_MAILBOX);
+
+			/* Check whether the incoming message is valid.                     */
+			if (incoming_message_p == NULL)
+			{
+				ATP_UART_UNRECOVERABLE_ERROR (RVM_INTERNAL_ERR,
+											  "  ATP-UART (handle_msg). Invalid event occurred ");
+				return (RVM_INTERNAL_ERR);
+			}
+			rvf_send_trace ("  ATP-UART (handle_msg). Unexpected message received ",
+							53,
+							incoming_message_p->msg_id,
+							RV_TRACE_LEVEL_WARNING,
+							ATP_USE_ID);
+			(void) rvf_free_buf ((T_RVF_BUFFER *) (incoming_message_p));
+		}
+
+		/* Now, attempt forwarding data to the AT Parser. Thus, initialize the  */
+		/* amount of data to be forwarded.                                      */
+		in_buffer_size = (UINT32) (ATP_UART_MAX_PACKET_SIZE - \
+								   (gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).nb_bytes_left);
+
+		/* Then, wait for data from the COM port. If any error occurred, then   */
+		/* abort.                                                               */
+		if (atp_uart_read_com_port (&((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[(gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).nb_bytes_left]), \
+									&in_buffer_size) == RV_OK)
+		{
+
+			/* Declare local block variables.                                   */
+			UINT32          in_buffer_begin = 0x00000000;
+			UINT32          in_buffer_end   = 0x00000000;
+			T_ATP_CMD       *cmd_info_p     = NULL;
+			T_ATP_CMD_NB    cmd_nb          = 0x0000;
+			T_ATP_CMD_TYPE  cmd_type        = UNKNOWN;
+
+			/* Send every 'Text Command' to the AT Parser separately.           */
+			while (in_buffer_end < in_buffer_size)
+			{
+
+				/* Skip leading <CR> and <LF> characters.                       */
+				for (in_buffer_begin = in_buffer_end;
+					 (in_buffer_begin < in_buffer_size) && \
+					 (((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[in_buffer_begin] == ATP_LF_CHARACTER) || \
+					  ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[in_buffer_begin] == ATP_CR_CHARACTER));
+					 in_buffer_begin++)
+				{
+				}
+
+				/* Get the 'Text Command' length by searching for the ending    */
+				/* <CR> character.                                              */
+				for (in_buffer_end = in_buffer_begin;
+					 (in_buffer_end < in_buffer_size) && \
+					 ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[in_buffer_end] != ATP_CR_CHARACTER);
+					 in_buffer_end++)
+				{
+				}
+
+				/* Abort whether no ending <CR> character found.                */
+				if ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[in_buffer_end] != ATP_CR_CHARACTER)
+				{
+
+					/* Update the number of bytes left.                         */
+					in_buffer_size -= in_buffer_begin;
+
+					/* Defrag.                                                  */
+					memcpy ((void *) ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p),
+							(void *) (&((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[in_buffer_begin])),
+							in_buffer_size);
+
+					/* Update the number of bytes left.                         */
+					(gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).nb_bytes_left = in_buffer_size;
+					break;
+				}
+
+				/* Otherwise, replace the ending <CR> character by NULL.        */
+				/* Indeed, such a 'Text Command' must be a NULL-terminated      */
+				/* string.                                                      */
+				(gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[in_buffer_end++] = '\x00';
+				rvf_send_trace (&((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[in_buffer_begin]),
+								(UINT8) (in_buffer_end - in_buffer_begin - 0x01),
+								NULL_PARAM,
+								RV_TRACE_LEVEL_DEBUG_LOW,
+								ATP_USE_ID);
+
+				/* Check whether the 'Text Command' is a final result code.     */
+				if ((atp_translate_txt_to_cmd (&((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[in_buffer_begin]), \
+											   UNKNOWN, \
+											   &cmd_type, \
+											   &cmd_nb, \
+											   (gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).atp_id, \
+											   &cmd_info_p) == RV_OK) && \
+					(cmd_type == RESULT_CODE))
+				{
+
+					/* If needed, de-allocate the command-related information.  */
+					if (cmd_info_p != NULL)
+					{
+						(void) rvf_free_buf ((T_RVF_BUFFER *) (cmd_info_p));
+					}
+
+					/* Check whether the 'Text Command' corresponds to the 'OK' */
+					/* final result code.                                       */
+					if (cmd_nb == ATP_OK_NB)
+					{
+						rvf_send_trace ("  ATP-UART (handle_msg). Echo mode switched off ",
+										48,
+										NULL_PARAM,
+										RV_TRACE_LEVEL_DEBUG_LOW,
+										ATP_USE_ID);
+
+						/* The echo mode is properly switched off.              */
+						echo_mode_switched_off = TRUE;
+						break;
+					}
+					ATP_UART_UNRECOVERABLE_ERROR (RVM_INTERNAL_ERR,
+												  "  ATP-UART (handle_msg). Echo mode not switched off ");
+					return (RVM_INTERNAL_ERR);
+				}
+
+				/* If needed, de-allocate the command-related information.      */
+				if (cmd_info_p != NULL)
+				{
+					(void) rvf_free_buf ((T_RVF_BUFFER *) (cmd_info_p));
+				}
+			}
+			continue;
+		}
+		rvf_send_trace ("  ATP-UART (handle_msg). Failed in getting data from the COM port ",
+						66,
+						NULL_PARAM,
+						RV_TRACE_LEVEL_WARNING,
+						ATP_USE_ID);
+	}
+
+	/* At last, initialize the remainder of the return path in order to receive */
+	/* events from the AT parser.                                               */
+	return_path.addr_id = gbl_atp_uart_ctrl_blk_p->addr_id;
+	
+	/* Register the ATP-UART interface to the AT Parser. If any error occurred, */
+	/* then call the function used whenever any unrecoverable error occurs and  */
+	/* abort.                                                                   */
+	if (atp_reg (name, \
+				 return_path, \
+				 mode, \
+				 &((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).atp_id)) != RV_OK)
+	{
+		ATP_UART_UNRECOVERABLE_ERROR (RVM_INTERNAL_ERR,
+									  "  ATP-UART (handle_msg). Registration failed ");
+		return (RVM_INTERNAL_ERR);
+	}
+	rvf_send_trace ("  ATP-UART (handle_msg). Registration completed ",
+					48,
+					NULL_PARAM,
+					RV_TRACE_LEVEL_DEBUG_LOW,
+					ATP_USE_ID);
+
+	/* Now, wait for the next events to be handled as long as no error occurs.  */
+	while (error_occurred == FALSE)
+	{
+
+		/* Wait for the next event(s) of interest.                              */
+		event_pending = rvf_wait (ATP_UART_ALL_EVENT_FLAGS,
+								  0x00000001);
+
+		/* If an expected event occurred, then get the associated message from  */
+		/* the mailbox dedicated to the ATP-UART interface.                     */
+		if (event_pending & ATP_UART_EXPECTED_EVENT)
+		{
+
+			/* Declare a local block variable.                                  */
+			T_RV_HDR  *incoming_message_p = NULL;
+
+			/* Get the incoming message from the mailbox dedicated to the       */
+			/* ATP-UART interface.                                              */
+			incoming_message_p = (T_RV_HDR *) rvf_read_mbox (ATP_UART_MAILBOX);
+
+			/* Check whether the incoming message is valid.                     */
+			if (incoming_message_p == NULL)
+			{
+				ATP_UART_UNRECOVERABLE_ERROR (RVM_INTERNAL_ERR,
+											  "  ATP-UART (handle_msg). Invalid event occurred ");
+				return (RVM_INTERNAL_ERR);
+			}
+			switch (incoming_message_p->msg_id)
+			{
+
+				/* 'ATP Open Port Indication'.                                  */
+				case ATP_OPEN_PORT_IND:
+					{
+
+						/* Declare local block variables.                       */
+						T_ATP_PORT_INFO             gsm_port_info      = {NOT_DEFINED_CONFIG, \
+																		  ATP_NO_RING_TYPE, \
+																		  ATP_ALL_THE_SIGNAL_UNMASK, \
+																		  0x0000};
+						T_ATP_NO_COPY_INFO          gsm_no_copy_info   = {RVF_INVALID_MB_ID, \
+																		  RVF_INVALID_MB_ID, \
+																		  TX_HEADER_OFF, \
+																		  0x00, \
+																		  0x00, \
+																		  RX_HEADER_OFF, \
+																		  0x00, \
+																		  0x00, \
+																		  NORMAL_PACKET};
+						T_ATP_CUSTOM_FROM_GSM_INFO  *gsm_custom_info_p = NULL;
+
+						rvf_send_trace ("  ATP-UART (handle_msg). 'ATP Open Port Indication' received ",
+										61,
+										NULL_PARAM,
+										RV_TRACE_LEVEL_DEBUG_MEDIUM,
+										ATP_USE_ID);
+
+						/* Set custom information associated with the pseudo    */
+						/* GSM Software Entity. If insufficient resources, then */
+						/* call the function used whenever any unrecoverable    */
+						/* error occurs and abort.                              */
+						if (rvf_get_buf (gbl_atp_uart_ctrl_blk_p->mb_id, \
+										 sizeof (T_ATP_CUSTOM_FROM_GSM_INFO), \
+										 (T_RVF_BUFFER **) (&gsm_custom_info_p)) == RVF_RED)
+						{
+							ATP_UART_UNRECOVERABLE_ERROR (RVM_MEMORY_ERR,
+														  "  ATP-UART (handle_msg). Insufficient resources ");
+							return (RVM_MEMORY_ERR);
+						}
+						gsm_custom_info_p->custom_type                 = ATP_FROM_GSM_INFO;
+						gsm_custom_info_p->optimal_gsm_max_packet_size = ATP_UART_MAX_PACKET_SIZE;
+
+						/* Open the virtual modem port with the AT Parser. If   */
+						/* any error occurred, then de-allocate custom          */
+						/* information associated with the pseudo GSM Software  */
+						/* Entity, call the function used whenever any          */
+						/* unrecoverable error occurs and abort.                */
+						if (atp_open_port_rsp (((T_ATP_OPEN_PORT_IND *) (incoming_message_p))->initiator_id, \
+											   ((T_ATP_OPEN_PORT_IND *) (incoming_message_p))->initiator_port_nb, \
+											   (gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).atp_id, \
+											   ATP_UART_GSM_PORT_NB, \
+											   gsm_port_info, \
+											   gsm_no_copy_info, \
+											   (T_ATP_CUSTOM_INFO *) (gsm_custom_info_p), \
+											   OPEN_PORT_OK) != RV_OK)
+						{
+							(void) rvf_free_buf ((T_RVF_BUFFER *) (gsm_custom_info_p));
+							ATP_UART_UNRECOVERABLE_ERROR (RVM_INTERNAL_ERR,
+														  "  ATP-UART (handle_msg). Unable to open the virtual modem port with the AT Parser ");
+							return (RVM_INTERNAL_ERR);
+						}
+						rvf_send_trace ("  ATP-UART (handle_msg). Virtual modem port properly established with the AT Parser ",
+										84,
+										NULL_PARAM,
+										RV_TRACE_LEVEL_DEBUG_LOW,
+										ATP_USE_ID);
+
+						/* The virtual modem port opened with the AT Parser is  */
+						/* now properly initialized.                            */
+						(gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).virtual_modem_port_established = TRUE;
+
+						/* If needed, de-allocate custom information contained  */
+						/* in the 'ATP Open Port Indication'.                   */
+						if (((T_ATP_OPEN_PORT_IND *) incoming_message_p)->custom_info_p != NULL)
+						{
+							rvf_free_buf ((T_RVF_BUFFER *) (((T_ATP_OPEN_PORT_IND *) (incoming_message_p))->custom_info_p));
+						}
+						break;
+					}
+
+				/* 'ATP Text Command Ready'.                                    */
+				case ATP_TXT_CMD_RDY:
+					{
+
+						/* Declare local block variables.                       */
+						UINT8              txt_cmd_length = 0x00;
+						T_ATP_TXT_CMD_RDY  *txt_cmd_rdy_p = (T_ATP_TXT_CMD_RDY *) (incoming_message_p);
+
+						rvf_send_trace ("  ATP-UART (handle_msg). 'ATP Text Command Ready' received ",
+										59,
+										NULL_PARAM,
+										RV_TRACE_LEVEL_DEBUG_MEDIUM,
+										ATP_USE_ID);
+
+						/* If any error occurred, then abort.                   */
+						if ((txt_cmd_rdy_p->port_nb != ATP_UART_GSM_PORT_NB) || \
+							(txt_cmd_rdy_p->txt_cmd_p == NULL))
+						{
+							rvf_send_trace ("  ATP-UART (handle_msg). 'Text Command' transfer failed ",
+											56,
+											NULL_PARAM,
+											RV_TRACE_LEVEL_WARNING,
+											ATP_USE_ID);
+							break;
+						}
+
+						/* Get the length of the 'Text Command'. Note that such */
+						/* a 'Text Command' is a NULL-terminated string.        */
+						txt_cmd_length = (UINT8) (strlen (txt_cmd_rdy_p->txt_cmd_p));
+						rvf_send_trace (txt_cmd_rdy_p->txt_cmd_p,
+										txt_cmd_length,
+										NULL_PARAM,
+										RV_TRACE_LEVEL_DEBUG_LOW,
+										ATP_USE_ID);
+
+						/* Forward the 'Text Command' to the COM port. If any   */
+						/* error occurred, then proceed.                        */
+						txt_cmd_rdy_p->txt_cmd_p[txt_cmd_length] = ATP_CR_CHARACTER;
+						if (atp_uart_write_com_port ((UINT8 *) (txt_cmd_rdy_p->txt_cmd_p), \
+													 (txt_cmd_length + 0x00000001)) != RV_OK)
+						{
+							rvf_send_trace ("  ATP-UART (handle_msg). 'Text Command' transfer failed ",
+											56,
+											NULL_PARAM,
+											RV_TRACE_LEVEL_WARNING,
+											ATP_USE_ID);
+						}
+
+						/* De-allocate the data buffer provided with the 'ATP   */
+						/* Command Ready'.                                      */
+						(void) rvf_free_buf ((T_RVF_BUFFER *) (txt_cmd_rdy_p->txt_cmd_p));
+						break;
+					}
+
+				/* 'ATP No Copy Data Ready'.                                    */
+				case ATP_NO_COPY_DATA_RDY:
+					{
+
+						/* Declare a local block variable.                      */
+						T_ATP_NO_COPY_DATA_RDY  *no_copy_data_rdy_p = (T_ATP_NO_COPY_DATA_RDY *) (incoming_message_p);
+
+						rvf_send_trace ("  ATP-UART (handle_msg). 'ATP No Copy Data Ready' received ",
+										59,
+										NULL_PARAM,
+										RV_TRACE_LEVEL_DEBUG_MEDIUM,
+										ATP_USE_ID);
+
+						/* If any error occurred, then abort.                   */
+						if ((no_copy_data_rdy_p->port_nb != ATP_UART_GSM_PORT_NB) || \
+							(no_copy_data_rdy_p->atp_buffer_p == NULL))
+						{
+							rvf_send_trace ("  ATP-UART (handle_msg). Data transfer to the COM port failed ",
+											62,
+											NULL_PARAM,
+											RV_TRACE_LEVEL_WARNING,
+											ATP_USE_ID);
+							break;
+						}
+						rvf_send_trace ("  ATP-UART (handle_msg). Data size ",
+										35,
+										no_copy_data_rdy_p->buffer_size,
+										RV_TRACE_LEVEL_DEBUG_LOW,
+										ATP_USE_ID);
+
+						/* Forward data to the COM port. If any error occurred, */
+						/* then proceed.                                        */
+						if (atp_uart_write_com_port (no_copy_data_rdy_p->atp_buffer_p, \
+													 no_copy_data_rdy_p->buffer_size) != RV_OK)
+						{
+							rvf_send_trace ("  ATP-UART (handle_msg). Data transfer to the COM port failed ",
+											62,
+											NULL_PARAM,
+											RV_TRACE_LEVEL_WARNING,
+											ATP_USE_ID);
+						}
+
+						/* De-allocate the data buffer provided with the 'ATP   */
+						/* No Copy Data Ready'.                                 */
+						(void) rvf_free_buf ((T_RVF_BUFFER *) (no_copy_data_rdy_p->atp_buffer_p));
+						break;
+					}
+
+				/* 'ATP Signal Changed'.                                        */
+				case ATP_SIGNAL_CHANGED:
+					{
+
+						/* Declare a local block variable.                      */
+						T_ATP_SIGNAL_CHANGED  *signal_changed_p = (T_ATP_SIGNAL_CHANGED *) (incoming_message_p);
+
+						rvf_send_trace ("  ATP-UART (handle_msg). 'ATP Signal Changed' received ",
+										55,
+										NULL_PARAM,
+										RV_TRACE_LEVEL_DEBUG_MEDIUM,
+										ATP_USE_ID);
+
+						/* If any error occurred, then abort.                   */
+						if (signal_changed_p->port_nb != ATP_UART_GSM_PORT_NB)
+						{
+							rvf_send_trace ("  ATP-UART (handle_msg). Invalid port number ",
+											45,
+											NULL_PARAM,
+											RV_TRACE_LEVEL_WARNING,
+											ATP_USE_ID);
+							break;
+						}
+						rvf_send_trace ("  ATP-UART (handle_msg). Bit mask ",
+										34,
+										signal_changed_p->signal,
+										RV_TRACE_LEVEL_DEBUG_LOW,
+										ATP_USE_ID);
+
+						/* Update the RS232 control signals associated with the */
+						/* virtual modem port.                                  */
+						(gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).control_signals = signal_changed_p->signal;
+						break;
+					}
+
+				/* 'ATP Port Mode Changed'.                                     */
+				case ATP_PORT_MODE_CHANGED:
+					{
+
+						/* Declare a local block variable.                      */
+						T_ATP_PORT_MODE_CHANGED  *port_mode_changed_p = (T_ATP_PORT_MODE_CHANGED *) (incoming_message_p);
+
+						rvf_send_trace ("  ATP-UART (handle_msg). 'ATP Port Mode Changed' received ",
+										58,
+										NULL_PARAM,
+										RV_TRACE_LEVEL_DEBUG_MEDIUM,
+										ATP_USE_ID);
+
+						/* If any error occurred, then abort.                   */
+						if (port_mode_changed_p->port_nb != ATP_UART_GSM_PORT_NB)
+						{
+							rvf_send_trace ("  ATP-UART (handle_msg). Invalid port number ",
+											45,
+											NULL_PARAM,
+											RV_TRACE_LEVEL_WARNING,
+											ATP_USE_ID);
+							break;
+						}
+						rvf_send_trace ("  ATP-UART (handle_msg). Mode ",
+										30,
+										port_mode_changed_p->mode,
+										RV_TRACE_LEVEL_DEBUG_LOW,
+										ATP_USE_ID);
+
+						/* If the virtual modem port is in 'Data' mode, then    */
+						/* send the escape sequence first.                      */
+						if ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).virtual_modem_port_mode == ATP_PORT_DATA_MODE)
+						{
+
+							/* Forward the escape sequence to the COM port. If  */
+							/* any error occurred, then call the function used  */
+							/* whenever any unrecoverable error occurs and      */
+							/* abort.                                           */
+							if (atp_uart_write_com_port ((UINT8 *) (ATP_ESCAPE_SEQUENCE), \
+														 (sizeof (ATP_ESCAPE_SEQUENCE) - 0x00000001)) != RV_OK)
+							{
+								ATP_UART_UNRECOVERABLE_ERROR (RVM_INTERNAL_ERR,
+															  "  ATP-UART (handle_msg). 'Escape sequence' not transmitted ");
+								return (RVM_INTERNAL_ERR);
+							}
+							rvf_send_trace ("  ATP-UART (handle_msg). 'Escape sequence' properly transmitted ",
+											64,
+											NULL_PARAM,
+											RV_TRACE_LEVEL_DEBUG_LOW,
+											ATP_USE_ID);
+						}
+
+						/* Update the mode of the virtual modem port.           */
+						(gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).virtual_modem_port_mode = port_mode_changed_p->mode;
+						break;
+					}
+
+				/* 'ATP Port Closed'.                                           */
+				case ATP_PORT_CLOSED:
+					{
+						rvf_send_trace ("  ATP-UART (handle_msg). 'ATP Port Closed' received ",
+										52,
+										NULL_PARAM,
+										RV_TRACE_LEVEL_DEBUG_MEDIUM,
+										ATP_USE_ID);
+
+						/* If any error occurred, then abort.                   */
+						if (((T_ATP_PORT_CLOSED *) (incoming_message_p))->port_nb != ATP_UART_GSM_PORT_NB)
+						{
+							rvf_send_trace ("  ATP-UART (handle_msg). Invalid port number ",
+											45,
+											NULL_PARAM,
+											RV_TRACE_LEVEL_WARNING,
+											ATP_USE_ID);
+							break;
+						}
+
+						/* The virtual modem port opened with the AT Parser is  */
+						/* now closed.                                          */
+						(gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).virtual_modem_port_established = FALSE;
+						break;
+					}
+
+				/* 'ATP-UART Start GSM'.                                        */
+				case ATP_UART_START_GSM:
+					{
+
+						/* Declare a local block variable.                      */
+						UINT8  gsm_init_p[] = {'A', 'T', '+', 'C', 'F', 'U', 'N', '=', '1', ';', '+', 'C', 'O', 'P', 'S', '=', '0', \
+												ATP_CR_CHARACTER};
+
+						rvf_send_trace ("  ATP-UART (handle_msg). 'ATP-UART Start GSM' received ",
+										55,
+										NULL_PARAM,
+										RV_TRACE_LEVEL_DEBUG_MEDIUM,
+										ATP_USE_ID);
+
+						/* If any error occurred, then abort.                   */
+						if (atp_uart_write_com_port (gsm_init_p, \
+													 sizeof (gsm_init_p)) != RV_OK)
+						{
+							rvf_send_trace ("  ATP-UART (handle_msg). Unable to start the GSM protocol stack ",
+											64,
+											NULL_PARAM,
+											RV_TRACE_LEVEL_WARNING,
+											ATP_USE_ID);
+							break;
+						}
+						break;
+					}
+
+				/* Unexpected message.                                          */
+				default:
+					{
+						rvf_send_trace ("  ATP-UART (handle_msg). Unexpected message received ",
+										53,
+										incoming_message_p->msg_id,
+										RV_TRACE_LEVEL_WARNING,
+										ATP_USE_ID);
+						break;
+					}
+			}
+			(void) rvf_free_buf ((T_RVF_BUFFER *) (incoming_message_p));
+		}
+
+		/* Now, if the flow control is activated, then proceed without getting  */
+		/* any data from the COM port.                                          */
+		if (((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).control_signals & ATP_RX_FLOW_UNMASK) == ATP_RX_FLOW_ON)
+		{
+			continue;
+		}
+
+		/* Otherwise, attempt forwarding data to the AT Parser. Thus,           */
+		/* initialize the amount of data to be forwarded.                       */
+		in_buffer_size = (UINT32) (ATP_UART_MAX_PACKET_SIZE - \
+								   (gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).nb_bytes_left);
+
+		/* Then, wait for data from the COM port. If any error occurred, then   */
+		/* abort.                                                               */
+		if (atp_uart_read_com_port (&((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[(gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).nb_bytes_left]), \
+									&in_buffer_size) != RV_OK)
+		{
+			rvf_send_trace ("  ATP-UART (handle_msg). Failed in getting data from the COM port ",
+							66,
+							NULL_PARAM,
+							RV_TRACE_LEVEL_WARNING,
+							ATP_USE_ID);
+			continue;
+		}
+
+		/* Take new data into account.                                          */
+		in_buffer_size = (UINT32) ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).nb_bytes_left + \
+								   in_buffer_size);
+
+		/* If no virtual modem port established with the AT Parser or if no     */
+		/* data pending for transmission to the AT Parser, then update the      */
+		/* number of bytes left and proceed.                                    */
+		if (((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).virtual_modem_port_established == FALSE) || \
+			(in_buffer_size == 0x00000000))
+		{
+			(gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).nb_bytes_left = in_buffer_size;
+			continue;
+		}
+
+		/* Otherwise, re-initialize the number of bytes left.                   */
+		(gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).nb_bytes_left = 0x00000000;
+		rvf_send_trace ("  ATP-UART (handle_msg). Get data from the COM port ",
+						52,
+						in_buffer_size,
+						RV_TRACE_LEVEL_DEBUG_LOW,
+						ATP_USE_ID);
+
+		/* At last, depending on the mode, transfert data from the COM port as  */
+		/* 'Text Command' or 'Data'.                                            */
+		if ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).virtual_modem_port_mode == ATP_PORT_CMD_MODE)
+		{
+
+			/* Declare local block variables.                                   */
+			UINT32          in_buffer_begin = 0x00000000;
+			UINT32          in_buffer_end   = 0x00000000;
+			T_ATP_CMD       *cmd_info_p     = NULL;
+			T_ATP_CMD_NB    cmd_nb          = 0x0000;
+			T_ATP_TXT_CMD   txt_cmd_p       = NULL;
+			T_ATP_CMD_TYPE  cmd_type        = UNKNOWN;
+
+			/* Send every 'Text Command' to the AT Parser separately.           */
+			while (in_buffer_end < in_buffer_size)
+			{
+
+				/* Skip leading <CR> and <LF> characters.                       */
+				for (in_buffer_begin = in_buffer_end;
+					 (in_buffer_begin < in_buffer_size) && \
+					 (((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[in_buffer_begin] == ATP_LF_CHARACTER) || \
+					  ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[in_buffer_begin] == ATP_CR_CHARACTER));
+					 in_buffer_begin++)
+				{
+				}
+
+				/* Get the 'Text Command' length by searching for the ending    */
+				/* <CR> character.                                              */
+				for (in_buffer_end = in_buffer_begin;
+					 (in_buffer_end < in_buffer_size) && \
+					 ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[in_buffer_end] != ATP_CR_CHARACTER);
+					 in_buffer_end++)
+				{
+				}
+
+				/* Abort whether no ending <CR> character found.                */
+				if ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[in_buffer_end] != ATP_CR_CHARACTER)
+				{
+
+					/* Update the number of bytes left.                         */
+					in_buffer_size -= in_buffer_begin;
+
+					/* Defrag.                                                  */
+					memcpy ((void *) ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p),
+							(void *) (&((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[in_buffer_begin])),
+							in_buffer_size);
+
+					/* Update the number of bytes left.                         */
+					(gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).nb_bytes_left = in_buffer_size;
+					break;
+				}
+
+				/* Otherwise, replace the ending <CR> character by NULL.        */
+				/* Indeed, such a 'Text Command' must be a NULL-terminated      */
+				/* string.                                                      */
+				(gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[in_buffer_end++] = '\x00';
+
+				/* Allocate memory in order to forward the 'Text Command' to    */
+				/* the AT Parser. If insufficient resources, then call the      */
+				/* function used whenever any unrecoverable error occurs and    */
+				/* abort.                                                       */
+				if (rvf_get_buf (gbl_atp_uart_ctrl_blk_p->mb_id, \
+								 (in_buffer_end - in_buffer_begin), \
+								 (T_RVF_BUFFER **) (&txt_cmd_p)) == RVF_RED)
+				{
+					ATP_UART_UNRECOVERABLE_ERROR (RVM_MEMORY_ERR,
+												  "  ATP-UART (handle_msg). Insufficient resources ");
+					break;
+				}
+
+				/* Copy the 'Text Command'.                                     */
+				memcpy ((void *) (txt_cmd_p),
+						(void *) (&((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[in_buffer_begin])),
+						(in_buffer_end - in_buffer_begin));
+				rvf_send_trace (txt_cmd_p,
+								(UINT8) (in_buffer_end - in_buffer_begin - 0x01),
+								NULL_PARAM,
+								RV_TRACE_LEVEL_DEBUG_LOW,
+								ATP_USE_ID);
+
+				/* Check whether the 'Text Command' is a final or an            */
+				/* unsolicited result code.                                     */
+				if ((atp_translate_txt_to_cmd (txt_cmd_p, \
+											   UNKNOWN, \
+											   &cmd_type, \
+											   &cmd_nb, \
+											   (gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).atp_id, \
+											   &cmd_info_p) == RV_OK) && \
+					(cmd_type == RESULT_CODE))
+				{
+
+					/* If the 'Text Command' corresponds to the 'Connect' final */
+					/* result code, then turn the 'Data Carrier Detect' on      */
+					/* before sending it to the AT Parser (See ITU-T            */
+					/* Recommendation V.250 ter page 32). If any error          */
+					/* occurred, then de-allocate the 'Text Command' and abort. */
+					if (cmd_nb == ATP_CONNECT_NB)
+					{
+						if (atp_set_signal ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).atp_id, \
+											ATP_UART_GSM_PORT_NB, \
+											ATP_DCD_1, \
+											ATP_DCD_UNMASK) != RV_OK)
+						{
+							(void) rvf_free_buf ((T_RVF_BUFFER *) (txt_cmd_p));
+
+							/* If needed, de-allocate the command-related       */
+							/* information.                                     */
+							if (cmd_info_p != NULL)
+							{
+								(void) rvf_free_buf ((T_RVF_BUFFER *) (cmd_info_p));
+							}
+							rvf_send_trace ("  ATP-UART (handle_msg). 'Data Carrier Detect' not turned on ",
+											61,
+											NULL_PARAM,
+											RV_TRACE_LEVEL_WARNING,
+											ATP_USE_ID);
+							break;
+						}
+						rvf_send_trace ("  ATP-UART (handle_msg). 'Data Carrier Detect' properly turned on ",
+										66,
+										NULL_PARAM,
+										RV_TRACE_LEVEL_DEBUG_LOW,
+										ATP_USE_ID);
+					}
+				}
+
+				/* Otherwise, the 'Text Command' is recognized as a preliminary */
+				/* result code.                                                 */
+				else
+				{
+					cmd_type = PRELIMINARY_RESULT_CODE;
+				}
+
+				/* If needed, de-allocate the command-related information.      */
+				if (cmd_info_p != NULL)
+				{
+					(void) rvf_free_buf ((T_RVF_BUFFER *) (cmd_info_p));
+				}
+
+				/* Forward the 'Text Command' to the AT Parser. If any error    */
+				/* occurred, then de-allocate the 'Text Command' and abort.     */
+				if (atp_send_txt_cmd ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).atp_id, \
+									  ATP_UART_GSM_PORT_NB, \
+									  cmd_type, \
+									  txt_cmd_p) != RV_OK)
+				{
+					(void) rvf_free_buf ((T_RVF_BUFFER *) (txt_cmd_p));
+					rvf_send_trace ("  ATP-UART (handle_msg). 'Text Command' failed ",
+									47,
+									NULL_PARAM,
+									RV_TRACE_LEVEL_WARNING,
+									ATP_USE_ID);
+					break;
+				}
+			}
+		}
+		else
+		{
+
+			/* Declare local block variables.                                   */
+			UINT8         no_carrier_count = 0x00;
+			UINT8         no_carrier_p[]   = {ATP_CR_CHARACTER, \
+											  ATP_LF_CHARACTER, \
+											  'N', 'O', ' ', 'C', 'A', 'R', 'R', 'I', 'E', 'R', \
+											  ATP_CR_CHARACTER, \
+											  ATP_LF_CHARACTER};
+			UINT8         ok_count         = 0x00;
+			UINT8         ok_p[]           = {ATP_CR_CHARACTER, \
+											  ATP_LF_CHARACTER, \
+											  'O', 'K', \
+											  ATP_CR_CHARACTER, \
+											  ATP_LF_CHARACTER};
+			UINT32        in_buffer_count  = 0x00000000;
+			UINT32        in_data_size     = 0x00000000;
+			T_ATP_CMD_NB  result_code_nb   = ATP_MAX_NB_OF_RESULT_CODES;
+
+			/* First, search for 'Ok' or 'No Carrier' final result codes.       */
+			for (in_buffer_count = 0x00000000, \
+				 in_data_size    = in_buffer_size;
+				 in_buffer_count < in_buffer_size;
+				 in_buffer_count++)
+			{
+
+				/* Search for an 'Ok' final result code.                        */
+				if ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[in_buffer_count] == ok_p[ok_count])
+				{
+
+					/* 'Ok' final result code detected.                         */
+					if (++ok_count == sizeof (ok_p))
+					{
+						result_code_nb = ATP_OK_NB;
+						rvf_send_trace ("  ATP-UART (handle_msg). 'Ok' final result code detected ",
+										57,
+										NULL_PARAM,
+										RV_TRACE_LEVEL_DEBUG_LOW,
+										ATP_USE_ID);
+
+						/* Send the remainder to the AT Parser.                 */
+						in_data_size = in_buffer_count - (sizeof (ok_p) - 0x00000001);
+						break;
+					}
+				}
+				else
+				{
+					ok_count = 0x00;
+				}
+
+				/* Search for a 'No Carrier' final result code.                 */
+				if ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[in_buffer_count] == no_carrier_p[no_carrier_count])
+				{
+
+					/* 'No Carrier' final result code detected.                 */
+					if (++no_carrier_count == sizeof (no_carrier_p))
+					{
+						result_code_nb = ATP_NO_CARRIER_NB;
+						rvf_send_trace ("  ATP-UART (handle_msg). 'No Carrier' final result code detected ",
+										65,
+										NULL_PARAM,
+										RV_TRACE_LEVEL_DEBUG_LOW,
+										ATP_USE_ID);
+
+						/* Send the remainder to the AT Parser.                 */
+						in_data_size = in_buffer_count - (sizeof (no_carrier_p) - 0x00000001);
+						break;
+					}
+				}
+				else
+				{
+					no_carrier_count = 0x00;
+				}
+			}
+
+			/* Then, check for some bytes to be forwarded data to the AT        */
+			/* Parser.                                                          */
+			if (in_data_size > 0x00000000)
+			{
+
+				/* Forward data to the AT Parser. If any error occurred, then   */
+				/* proceed.                                                     */
+				if (atp_send_data ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).atp_id, \
+								   ATP_UART_GSM_PORT_NB, \
+								   (void *) ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p), \
+								   in_data_size, \
+								   &((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).nb_bytes_left)) != RV_OK)
+				{
+					rvf_send_trace ("  ATP-UART (handle_msg). Data transfer to the AT Parser failed ",
+									63,
+									NULL_PARAM,
+									RV_TRACE_LEVEL_WARNING,
+									ATP_USE_ID);
+				}
+
+				/* Update the number of bytes left.                             */
+				in_data_size   -= (gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).nb_bytes_left;
+				in_buffer_size -= in_data_size;
+
+				/* Check whether some bytes left to be sent to the AT Parser.   */
+				if ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).nb_bytes_left > 0x00000000)
+				{
+
+					/* Defrag.                                                  */
+					memcpy ((void *) ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p),
+							(void *) (&((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[in_data_size])),
+							in_buffer_size);
+
+					/* Update the number of bytes left.                         */
+					(gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).nb_bytes_left = in_buffer_size;
+					continue;
+				}
+			}
+
+			/* At last, check whether an 'Ok' or a 'No Carrier' final result    */
+			/* code was detected.                                               */
+			if (result_code_nb != ATP_MAX_NB_OF_RESULT_CODES)
+			{
+
+				/* Turn the 'Data Carrier Detect' off before sending it to the  */
+				/* AT Parser (See ITU-T Recommendation V.250 ter page 37).      */
+				/* However, proceed whether any error occurred.                 */
+				if (((atp_set_signal ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).atp_id, \
+									  ATP_UART_GSM_PORT_NB, \
+									  ATP_DCD_0, \
+									  ATP_DCD_UNMASK) != RV_OK) || \
+					 (atp_send_cmd ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).atp_id, \
+									ATP_UART_GSM_PORT_NB, \
+									RESULT_CODE, \
+									result_code_nb, \
+									NULL) != RV_OK)))
+				{
+					rvf_send_trace ("  ATP-UART (handle_msg). Final result code not transmitted ",
+									59,
+									NULL_PARAM,
+									RV_TRACE_LEVEL_WARNING,
+									ATP_USE_ID);
+				}
+
+				/* Update the number of bytes left.                             */
+				in_buffer_size -= in_buffer_count;
+
+				/* Update the mode of the virtual modem port.                   */
+				(gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).virtual_modem_port_mode = ATP_PORT_CMD_MODE;
+			}
+
+			/* If some data left, then defrag.                                  */
+			memcpy ((void *) ((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p),
+					(void *) (&((gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).in_buffer_p[in_buffer_count])),
+					in_buffer_size);
+
+			/* Update the number of bytes left.                                 */
+			(gbl_atp_uart_ctrl_blk_p->conn_ctrl_blk).nb_bytes_left = in_buffer_size;
+		}
+	}
+	return (RVM_OK);
+
+} /********************* End of atp_uart_handle_msg function ********************/