FreeCalypso > hg > tcs211-c139
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 ******************/