FreeCalypso > hg > fc-selenite
view src/cs/services/atp/atp_cmd.c @ 135:ac4c0a9bc022
FFS dev.c: change from Magnetite for potential future
embedded modem products with K5A32xxCTM flash chips
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 20 Dec 2018 04:24:06 +0000 |
parents | b6a5e36de839 |
children |
line wrap: on
line source
/******************************************************************************** * * 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 ******************/