/* * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The OpenAirInterface Software Alliance licenses this file to You under * the OAI Public License, Version 1.0 (the "License"); you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://www.openairinterface.org/?page_id=698 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ /***************************************************************************** Source at_command.c Version 0.1 Date 2012/03/07 Product NAS stack Subsystem Application Programming Interface Author Frederic Maurel, Baris Demiray Description Defines the ATtention (AT) command set supported by the NAS sublayer protocol *****************************************************************************/ #include "at_command.h" #include "commonDef.h" #include "nas_log.h" #include "at_error.h" #include // isspace, isdigit #include // strtol, malloc, free #include // strncpy, strstr, strchr, strcmp, strncasecmp // strlen, memmove, strdup, strtok #include // va_start, va_arg, va_end /****************************************************************************/ /**************** E X T E R N A L D E F I N I T I O N S ****************/ /****************************************************************************/ // FIXME Put this in .h extern int at_response_format_v1; extern int at_error_code_suppression_q1; extern at_error_format_t at_error_format; /****************************************************************************/ /******************* L O C A L D E F I N I T I O N S *******************/ /****************************************************************************/ /* Handlers used to parse AT commands */ static int parse_e0(const char*, int, at_command_t*); static int parse_e1(const char*, int, at_command_t*); static int parse_q0(const char*, int, at_command_t*); static int parse_q1(const char*, int, at_command_t*); static int parse_v0(const char*, int, at_command_t*); static int parse_v1(const char*, int, at_command_t*); static int parse_cgsn(const char*, int, at_command_t*); static int parse_cgsn_test(const char*, int, at_command_t*); static int parse_cgmi(const char*, int, at_command_t*); static int parse_cgmi_test(const char*, int, at_command_t*); static int parse_cgmm(const char*, int, at_command_t*); static int parse_cgmm_test(const char*, int, at_command_t*); static int parse_cgmr(const char*, int, at_command_t*); static int parse_cgmr_test(const char*, int, at_command_t*); static int parse_cimi(const char*, int, at_command_t*); static int parse_cimi_test(const char*, int, at_command_t*); static int parse_cfun_set(const char*, int, at_command_t*); static int parse_cfun_get(const char*, int, at_command_t*); static int parse_cfun_test(const char*, int, at_command_t*); static int parse_cpin_set(const char*, int, at_command_t*); static int parse_cpin_get(const char*, int, at_command_t*); static int parse_cpin_test(const char*, int, at_command_t*); static int parse_csq(const char*, int, at_command_t*); static int parse_csq_test(const char*, int, at_command_t*); static int parse_cesq(const char*, int, at_command_t*); static int parse_cesq_test(const char*, int, at_command_t*); static int parse_clac(const char*, int, at_command_t*); static int parse_clac_test(const char*, int, at_command_t*); static int parse_cmee_set(const char*, int, at_command_t*); static int parse_cmee_get(const char*, int, at_command_t*); static int parse_cmee_test(const char*, int, at_command_t*); static int parse_cnum(const char*, int, at_command_t*); static int parse_cnum_test(const char*, int, at_command_t*); static int parse_clck_set(const char*, int, at_command_t*); static int parse_clck_test(const char*, int, at_command_t*); static int parse_cops_set(const char*, int, at_command_t*); static int parse_cops_get(const char*, int, at_command_t*); static int parse_cops_test(const char*, int, at_command_t*); static int parse_creg_set(const char*, int, at_command_t*); static int parse_creg_get(const char*, int, at_command_t*); static int parse_creg_test(const char*, int, at_command_t*); static int parse_cgatt_set(const char*, int, at_command_t*); static int parse_cgatt_get(const char*, int, at_command_t*); static int parse_cgatt_test(const char*, int, at_command_t*); static int parse_cgreg_set(const char*, int, at_command_t*); static int parse_cgreg_get(const char*, int, at_command_t*); static int parse_cgreg_test(const char*, int, at_command_t*); static int parse_cereg_set(const char*, int, at_command_t*); static int parse_cereg_get(const char*, int, at_command_t*); static int parse_cereg_test(const char*, int, at_command_t*); static int parse_cgdcont_set(const char*, int, at_command_t*); static int parse_cgdcont_get(const char*, int, at_command_t*); static int parse_cgdcont_test(const char*, int, at_command_t*); static int parse_cgact_set(const char*, int, at_command_t*); static int parse_cgact_get(const char*, int, at_command_t*); static int parse_cgact_test(const char*, int, at_command_t*); static int parse_cgpaddr_set(const char*, int, at_command_t*); static int parse_cgpaddr_test(const char*, int, at_command_t*); /* List of AT command handlers */ typedef struct { char *command; int (*handler)(const char *, int, at_command_t*); at_command_type_t type; } at_command_handler_t; static const at_command_handler_t _at_command_handler[] = { /* TE-TA interface commands */ { "E0", parse_e0, AT_COMMAND_ACT }, { "E1", parse_e1, AT_COMMAND_ACT }, { "Q0", parse_q0, AT_COMMAND_ACT }, { "Q1", parse_q1, AT_COMMAND_ACT }, { "V0", parse_v0, AT_COMMAND_ACT }, { "V1", parse_v1, AT_COMMAND_ACT }, { "E0Q0V0", parse_v0, AT_COMMAND_ACT }, { "E0Q0V1", parse_v1, AT_COMMAND_ACT }, { "E1Q0V0", parse_v0, AT_COMMAND_ACT }, { "E1Q0V1", parse_v1, AT_COMMAND_ACT }, /* Request Product Serial Number identification (IMEI) */ { "+CGSN", parse_cgsn, AT_COMMAND_ACT }, { "+CGSN=?", parse_cgsn_test, AT_COMMAND_TST }, /* Request manufacturer identification */ { "+CGMI", parse_cgmi, AT_COMMAND_ACT }, { "+CGMI=?", parse_cgmi_test, AT_COMMAND_TST }, /* Request model identification */ { "+CGMM", parse_cgmm, AT_COMMAND_ACT }, { "+CGMM=?", parse_cgmm_test, AT_COMMAND_TST }, /* Request revision identification */ { "+CGMR", parse_cgmr, AT_COMMAND_ACT }, { "+CGMR=?", parse_cgmr_test, AT_COMMAND_TST }, /* Request International Mobile Subscriber Identity */ { "+CIMI", parse_cimi, AT_COMMAND_ACT }, { "+CIMI=?", parse_cimi_test, AT_COMMAND_TST }, /* Set phone functionality */ { "+CFUN=", parse_cfun_set, AT_COMMAND_SET }, { "+CFUN?", parse_cfun_get, AT_COMMAND_GET }, { "+CFUN=?", parse_cfun_test, AT_COMMAND_TST }, /* Enter PIN */ { "+CPIN=", parse_cpin_set, AT_COMMAND_SET }, { "+CPIN?", parse_cpin_get, AT_COMMAND_GET }, { "+CPIN=?", parse_cpin_test, AT_COMMAND_TST }, /* Signal quality */ { "+CSQ", parse_csq, AT_COMMAND_ACT }, { "+CSQ=?", parse_csq_test, AT_COMMAND_TST }, /* Extended signal quality */ { "+CESQ", parse_cesq, AT_COMMAND_ACT }, { "+CESQ=?", parse_cesq_test, AT_COMMAND_TST }, /* List all available AT commands */ { "+CLAC", parse_clac, AT_COMMAND_ACT }, { "+CLAC=?", parse_clac_test, AT_COMMAND_TST }, /* Report mobile termination error */ { "+CMEE=", parse_cmee_set, AT_COMMAND_SET }, { "+CMEE?", parse_cmee_get, AT_COMMAND_GET }, { "+CMEE=?", parse_cmee_test, AT_COMMAND_TST }, /* Subscriber number */ { "+CNUM", parse_cnum, AT_COMMAND_ACT }, { "+CNUM=?", parse_cnum_test, AT_COMMAND_TST }, /* Facility lock */ { "+CLCK=", parse_clck_set, AT_COMMAND_SET }, { "+CLCK=?", parse_clck_test, AT_COMMAND_TST }, /* PLMN selection */ { "+COPS=", parse_cops_set, AT_COMMAND_SET }, { "+COPS?", parse_cops_get, AT_COMMAND_GET }, { "+COPS=?", parse_cops_test, AT_COMMAND_TST }, /* Network registration */ { "+CREG=", parse_creg_set, AT_COMMAND_SET }, { "+CREG?", parse_creg_get, AT_COMMAND_GET }, { "+CREG=?", parse_creg_test, AT_COMMAND_TST }, /* GPRS service attach/detach */ { "+CGATT=", parse_cgatt_set, AT_COMMAND_SET }, { "+CGATT?", parse_cgatt_get, AT_COMMAND_GET }, { "+CGATT=?", parse_cgatt_test, AT_COMMAND_TST }, /* GPRS network registration status */ { "+CGREG=", parse_cgreg_set, AT_COMMAND_SET }, { "+CGREG?", parse_cgreg_get, AT_COMMAND_GET }, { "+CGREG=?", parse_cgreg_test, AT_COMMAND_TST }, /* EPS network registration status */ { "+CEREG=", parse_cereg_set, AT_COMMAND_SET }, { "+CEREG?", parse_cereg_get, AT_COMMAND_GET }, { "+CEREG=?", parse_cereg_test, AT_COMMAND_TST }, /* Define PDP Context */ { "+CGDCONT=", parse_cgdcont_set, AT_COMMAND_SET }, { "+CGDCONT?", parse_cgdcont_get, AT_COMMAND_GET }, { "+CGDCONT=?", parse_cgdcont_test, AT_COMMAND_TST }, /* PDP context activate or deactivate */ { "+CGACT=", parse_cgact_set, AT_COMMAND_SET }, { "+CGACT?", parse_cgact_get, AT_COMMAND_GET }, { "+CGACT=?", parse_cgact_test, AT_COMMAND_TST }, /* Show PDP address(es) */ { "+CGPADDR=", parse_cgpaddr_set, AT_COMMAND_SET }, { "+CGPADDR=?", parse_cgpaddr_test, AT_COMMAND_TST }, { "null", NULL } }; static int ParseString(char * at_str, at_command_t* at_command); static int ParseCommand(const unsigned char *str, const char *format, ...); static size_t GrabString(const unsigned char *str, char **output); static unsigned int NumberOfParameters(const unsigned char* str); static unsigned int IsNumeric(const char* str, size_t len); /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ /**************************************************************************** ** ** ** Name: at_command_decode() ** ** ** ** Description: Parses AT command line and accordingly fills data struc- ** ** ture. The main functions of the AT command parser are: ** ** - check the AT command syntax ** ** - fill parameter values into the data structure ** ** ** ** Inputs: buffer: Pointer to the buffer containing AT com- ** ** mand line ** ** length: Number of bytes that should be processed ** ** Others: None ** ** ** ** Outputs: at_command: AT command data structure to be filled ** ** Return: The number of AT commands successfully ** ** decoded; RETURNerror if an error occurred ** ** Others: None ** ** ** ***************************************************************************/ int at_command_decode(const char* buffer, int length, at_command_t* at_command) { LOG_FUNC_IN; int rc = RETURNok; if (length < 3) { /* Minimum size to carry an AT command is 3 */ LOG_TRACE(ERROR, "USR-API - Input is short of size to carry an AT command!"); return RETURNerror; } else if (strncasecmp(buffer, "AT", 2) != 0) { /* There must be AT initials in input... */ LOG_TRACE(ERROR, "USR-API - There is no proper initials (AT) in input!"); return RETURNerror; } else if (buffer[length - 1] != '\r') { /* And there must be CR at the end */ LOG_TRACE(ERROR, "USR-API - There is no Carriage Return at the end!"); return RETURNerror; } else if (strcasecmp(buffer, "AT\r") == 0) { /* AT command alone; just return OK */ at_command->id = 0; at_command->mask = AT_COMMAND_NO_PARAM; return (1); } /* Parse the AT command line */ int i; char* buf = strdup(buffer+2); char* cmd = strtok(buf, ";"); // FIXME check overflow for (i=0; cmd && (rc != RETURNerror); i++) { rc = ParseString(cmd, &at_command[i]); cmd = strtok(NULL, ";"); } free(buf); if (rc != RETURNerror) { LOG_FUNC_RETURN (i); } LOG_FUNC_RETURN (rc); } /**************************************************************************** ** ** ** Name: at_command_get_list() ** ** ** ** Description: Returns the list of supported AT commands. ** ** ** ** Inputs: buffer: Pointer to the buffer containing the ** ** string representaton of the first AT com- ** ** mand that is supported by the NAS sublayer ** ** n_max: Maximum number of AT commands the buffer ** ** may contain ** ** Others: None ** ** ** ** Outputs: None ** ** Return: The number of AT commands actually suppor- ** ** ted by the NAS sublayer ** ** Others: None ** ** ** ***************************************************************************/ int at_command_get_list(const char** buffer, int n_max) { LOG_FUNC_IN; int handler_index = 0; while ( (strcmp(_at_command_handler[handler_index].command, "null") != 0) && (handler_index < n_max) ) { *buffer++ = _at_command_handler[handler_index++].command; } LOG_FUNC_RETURN (handler_index); } /****************************************************************************/ /********************* L O C A L F U N C T I O N S *********************/ /****************************************************************************/ /**************************************************************************** ** ** ** Name: ParseString() ** ** ** ** Description: Calls the appropriate parsing handler after having ** ** successfully parsed the AT command prefix. ** ** ** ** Inputs: at_str: Pointer to the buffer containing AT com- ** ** mand line ** ** Others: None ** ** ** ** Outputs: at_command: AT command structure to be filled ** ** Return: The AT command identifier when the buffer ** ** has been successfully processed; ** ** RETURNerror otherwise. ** ** Others: None ** ** ** ***************************************************************************/ static int ParseString(char * at_str, at_command_t* at_command) { char* terminal_character_index = NULL; int num_of_chars_to_compare = -1; int handler_index; int handler_found = FALSE; int check_for_carriage_return_index = 0; /* * Find the number of characters we should be comparing against * the command list */ if ((terminal_character_index = strstr(at_str, "=?")) != NULL) { /* `test' command */ num_of_chars_to_compare = terminal_character_index - at_str + 2; check_for_carriage_return_index = 1; at_command->type = AT_COMMAND_TST; } else if ((terminal_character_index = strchr(at_str, '?')) != NULL) { /* `read' command */ num_of_chars_to_compare = terminal_character_index - at_str + 1; check_for_carriage_return_index = 1; at_command->type = AT_COMMAND_GET; } else if ((terminal_character_index = strchr(at_str, '=')) != NULL) { /* `set' command */ num_of_chars_to_compare = terminal_character_index - at_str + 1; at_command->type = AT_COMMAND_SET; } else if ((terminal_character_index = strchr(at_str, '\r')) != NULL) { /* Basic/action command */ num_of_chars_to_compare = terminal_character_index - at_str; check_for_carriage_return_index = 1; at_command->type = AT_COMMAND_ACT; } else { /* One action command among many commands */ num_of_chars_to_compare = strchr(at_str, '\0') - at_str; at_command->type = AT_COMMAND_ACT; } /* * The AT command strings in `Commands' list (that we compare the incoming * command against) don't have CR at the end. So we have to ensure that CR * comes just after characters like = and ? */ if (check_for_carriage_return_index == 1) { if ( (at_str[num_of_chars_to_compare] != '\0') && (at_str[num_of_chars_to_compare] != '\r') ) { LOG_TRACE(ERROR, "USR-API - Carriage return is not at where it should be!"); return RETURNerror; } } /* Check if this command has a relevant command handler */ for (handler_index=0; strcmp(_at_command_handler[handler_index].command, "null") != 0; handler_index++) { /* First match the command types... */ if (at_command->type != _at_command_handler[handler_index].type) continue; /* Match the command length... */ if (strlen(_at_command_handler[handler_index].command) != num_of_chars_to_compare) continue; /* Now do string comparison... */ if (strncasecmp(at_str, _at_command_handler[handler_index].command, num_of_chars_to_compare) != 0) continue; handler_found = TRUE; break; } /* Call the relevant handler or return with error */ if (!handler_found) { LOG_TRACE(ERROR, "USR-API - Unsupported or invalid command!"); return RETURNerror; } return _at_command_handler[handler_index].handler(at_str, num_of_chars_to_compare, at_command); } /**************************************************************************** ** ** ** Name: ParseCommand() ** ** ** ** Description: Parses the input string on the basis of the format string ** ** provided. ** ** ** ** Inputs: str: The string to be parsed ** ** format: The format of the input string ** ** Others: None ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** ** Others: None ** ** ** ***************************************************************************/ static int ParseCommand(const unsigned char *str, const char *format, ...) { const unsigned char *fmt = (unsigned char*) format; const char *inp = (char*) str; char *endptr; char *out_us; char *buffer; size_t length; size_t storage_size; int *out_i; long int *out_l; va_list ap; int error = RETURNok; va_start(ap, format); while (*fmt) { switch (*fmt++) { case '@': if (*fmt == 0) { /* Invalid format string */ LOG_TRACE(ERROR, "USR-API - Invalid format string!"); error = RETURNerror; goto end; } switch (*fmt++) { case 'i': out_i = va_arg(ap, int *); *out_i = strtol(inp, &endptr, 10); if (endptr == inp) { error = RETURNerror; goto end; } inp = endptr; break; case 'I': out_i = va_arg(ap, int *); *out_i = strtol(inp, &endptr, 10); if (endptr == inp) { /* Number empty */ /* optional parameter ??? */ LOG_TRACE(WARNING, "USR-API - Number empty!"); *out_i = 0; } else { inp = endptr; } break; case 'l': out_l = va_arg(ap, long int *); *out_l = strtol(inp, &endptr, 10); if (endptr == inp) { error = RETURNerror; goto end; } inp = endptr; break; case 'r': out_us = va_arg(ap, char *); storage_size = va_arg(ap, size_t); length = GrabString((unsigned char*) inp, &buffer); if (strlen(buffer) > storage_size) { free(buffer); error = RETURNerror; goto end; } strcpy(out_us, buffer); free(buffer); inp += length; break; case '@': if (*inp++ != '@') { error = RETURNerror; goto end; } break; case '0': /* Just skip the rest */ goto end; default: /* Invalid format string */ error = RETURNerror; goto end; } break; case ' ': while (isspace(*inp)) inp++; break; default: if (*inp++ != *(fmt - 1)) { error = RETURNerror; goto end; } break; } } /* Ignore trailing spaces */ while (isspace(*inp)) inp++; if (*inp != 0) { error = RETURNerror; goto end; } end: va_end(ap); return error; } /**************************************************************************** ** ** ** Name: GrabString() ** ** ** ** Description: Grabs single string, removing possible quotes. ** ** ** ** Inputs: str: The string to be parsed ** ** Others: None ** ** ** ** Outputs: output: Allocated output string buffer ** ** Return: Length of parsed string ** ** Others: None ** ** ** ***************************************************************************/ static size_t GrabString(const unsigned char *str, char **output) { size_t size = 4, position = 0; int inside_quotes = 0; /* Allocate initial buffer in case string is empty */ *output = malloc(size); if (*output == NULL) { return 0; } while (inside_quotes || (*str != ',' && *str != ')' && *str != 0x0d && *str != 0x0a && *str != 0x00)) { /* Check for quotes */ if (*str == '"') { inside_quotes = !inside_quotes; } /* We also allocate space for trailing zero */ if (position + 2 > size) { size += 10; *output = realloc(*output, size); if (*output == NULL) { return 0; } } /* Copy to output */ (*output)[position] = *str; position++; str++; } (*output)[position] = 0; /* Strip quotes */ if ((*output)[0] == '"' && (*output)[position - 1]) { memmove(*output, (*output) + 1, position - 2); (*output)[position - 2] = 0; } return position; } /**************************************************************************** ** ** ** Name: NumberOfParameters() ** ** ** ** Description: Returns the number of parameters found in the given AT ** ** command line. ** ** ** ** Inputs: str: The string to be parsed ** ** Others: None ** ** ** ** Outputs: None ** ** Return: The number of parameter delimiter (comma) ** ** found in the input string buffer ** ** Others: None ** ** ** ***************************************************************************/ static unsigned int NumberOfParameters(const unsigned char* str) { if (*str == '\r') return 0; int count = 1; while (*str) { if (*str++ == ',') { ++count; } } return count; } /**************************************************************************** ** ** ** Name: IsNumeric() ** ** ** ** Description: Checks whether the input string buffer has all digits ** ** ** ** Inputs: str: The string to be parsed ** ** Others: None ** ** ** ** Outputs: None ** ** Return: TRUE, FALSE ** ** Others: None ** ** ** ***************************************************************************/ static unsigned int IsNumeric(const char* str, size_t len) { while (len-- > 0) { if (!isdigit(str[len])) { return FALSE; } } return TRUE; } /****************************************************************************/ /******************** Handlers used to parse AT commands ********************/ /****************************************************************************/ static int parse_e0(const char* string, int position, at_command_t* at_command) { /* Command echo E0 */ at_command->id = 0; at_command->mask = AT_COMMAND_NO_PARAM; return at_command->id; } static int parse_e1(const char* string, int position, at_command_t* at_command) { /* Command echo E1 */ at_command->id = 0; at_command->mask = AT_COMMAND_NO_PARAM; return at_command->id; } static int parse_q0(const char* string, int position, at_command_t* at_command) { /* Result code suppression Q0 */ at_error_code_suppression_q1 = FALSE; at_command->id = 0; at_command->mask = AT_COMMAND_NO_PARAM; return at_command->id; } static int parse_q1(const char* string, int position, at_command_t* at_command) { /* Result code suppression Q1 */ at_error_code_suppression_q1 = TRUE; at_command->id = 0; at_command->mask = AT_COMMAND_NO_PARAM; return at_command->id; } static int parse_v0(const char* string, int position, at_command_t* at_command) { /* Response format V0 (numeric result code + limited header) */ at_error_format = AT_ERROR_NUMERIC; at_response_format_v1 = FALSE; at_command->id = 0; at_command->mask = AT_COMMAND_NO_PARAM; return at_command->id; } static int parse_v1(const char* string, int position, at_command_t* at_command) { /* Response format V1 (verbose result code + full header) */ at_error_format = AT_ERROR_VERBOSE; at_response_format_v1 = TRUE; at_command->id = 0; at_command->mask = AT_COMMAND_NO_PARAM; return at_command->id; } static int parse_cgsn(const char* string, int position, at_command_t* at_command) { /* CGSN action command - No parameter */ at_command->id = AT_CGSN; at_command->mask = AT_COMMAND_CGSN_MASK; return at_command->id; } static int parse_cgsn_test(const char* string, int position, at_command_t* at_command) { /* CGSN test command - No parameter */ at_command->id = AT_CGSN; return at_command->id; } static int parse_cgmi(const char* string, int position, at_command_t* at_command) { /* CGMI action command - No parameter */ at_command->id = AT_CGMI; at_command->mask = AT_COMMAND_CGMI_MASK; return at_command->id; } static int parse_cgmi_test(const char* string, int position, at_command_t* at_command) { /* CGMI test command - No parameter */ at_command->id = AT_CGMI; return at_command->id; } static int parse_cgmm(const char* string, int position, at_command_t* at_command) { /* CGMM action command - No parameter */ at_command->id = AT_CGMM; at_command->mask = AT_COMMAND_CGMM_MASK; return at_command->id; } static int parse_cgmm_test(const char* string, int position, at_command_t* at_command) { /* CGMM test command - No parameter */ at_command->id = AT_CGMM; return at_command->id; } static int parse_cgmr(const char* string, int position, at_command_t* at_command) { /* CGMR action command - No parameter */ at_command->id = AT_CGMR; at_command->mask = AT_COMMAND_CGMR_MASK; return at_command->id; } static int parse_cgmr_test(const char* string, int position, at_command_t* at_command) { /* CGMR test command - No parameter */ at_command->id = AT_CGMR; return at_command->id; } static int parse_cimi(const char* string, int position, at_command_t* at_command) { /* CIMI action command - No parameter */ at_command->id = AT_CIMI; at_command->mask = AT_COMMAND_CIMI_MASK; return at_command->id; } static int parse_cimi_test(const char* string, int position, at_command_t* at_command) { /* CIMI test command - No parameter */ at_command->id = AT_CIMI; return at_command->id; } static int parse_cfun_set(const char* string, int position, at_command_t* at_command) { /* CFUN parameter command - Parameters [[,]] */ at_command->id = AT_CFUN; unsigned char* parameter_start_index = (unsigned char*) string + position; /* Check the number of parameters */ unsigned number_of_parameters = NumberOfParameters(parameter_start_index); /* Parse the parameters */ switch (number_of_parameters) { case 0: // No any parameter LOG_TRACE(INFO, "USR-API - Parsing of AT+CFUN= command succeed"); at_command->mask = AT_COMMAND_NO_PARAM; break; case 1: // Only parameter is present if (ParseCommand(parameter_start_index, "@i", &at_command->command.cfun.fun) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CFUN= command failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CFUN= command succeed (fun:%d)", at_command->command.cfun.fun); at_command->mask = AT_CFUN_FUN_MASK; break; case 2: // , parameters are present if (ParseCommand(parameter_start_index, "@i,@i", &at_command->command.cfun.fun, &at_command->command.cfun.rst) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CFUN=, command failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CFUN=, command succeed (fun:%d, rst:%d)", at_command->command.cfun.fun, at_command->command.cfun.rst); at_command->mask = AT_CFUN_FUN_MASK | AT_CFUN_RST_MASK; break; default: LOG_TRACE(ERROR, "USR-API - Invalid number of parameters (%d)", number_of_parameters); return RETURNerror; } return at_command->id; } static int parse_cfun_get(const char* string, int position, at_command_t* at_command) { /* CFUN action command - No parameter */ at_command->id = AT_CFUN; return at_command->id; } static int parse_cfun_test(const char* string, int position, at_command_t* at_command) { /* CFUN test command - No parameter */ at_command->id = AT_CFUN; return at_command->id; } static int parse_cpin_set(const char* string, int position, at_command_t* at_command) { /* CPIN parameter command - Parameters [,] */ at_command->id = AT_CPIN; unsigned char* parameter_start_index = (unsigned char*) string + position; /* Check the number of parameters */ unsigned number_of_parameters = NumberOfParameters(parameter_start_index); /* Parse the parameters */ switch (number_of_parameters) { case 1: // Only parameter is present if (ParseCommand(parameter_start_index, "@r", at_command->command.cpin.pin, AT_CPIN_SIZE) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CPIN= command failed"); return RETURNerror; } if (!IsNumeric(at_command->command.cpin.pin, AT_CPIN_SIZE)) { LOG_TRACE(ERROR, "USR-API - Incoming parameter is not a valid PIN code!"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CPIN= command succeed (pin:%s)", at_command->command.cpin.pin); at_command->mask = AT_COMMAND_NO_PARAM; break; case 2: // , parameters are present if (ParseCommand(parameter_start_index, "@r,@r", at_command->command.cpin.pin, AT_CPIN_SIZE, at_command->command.cpin.newpin, AT_CPIN_SIZE) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CPIN=, command failed"); return RETURNerror; } if (!IsNumeric(at_command->command.cpin.pin, AT_CPIN_SIZE) || !IsNumeric(at_command->command.cpin.newpin, AT_CPIN_SIZE)) { LOG_TRACE(ERROR, "USR-API - Incoming parameter is not a valid PIN code!"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CPIN=, command succeed (pin:%s, newpin:%s)", at_command->command.cpin.pin, at_command->command.cpin.newpin); at_command->mask = AT_CPIN_NEWPIN_MASK; break; default: LOG_TRACE(ERROR, "USR-API - Invalid number of parameters (%d)", number_of_parameters); return RETURNerror; } return at_command->id; } static int parse_cpin_get(const char* string, int position, at_command_t* at_command) { /* CPIN action command - No parameter */ at_command->id = AT_CPIN; return at_command->id; } static int parse_cpin_test(const char* string, int position, at_command_t* at_command) { /* CPIN test command - No parameter */ at_command->id = AT_CPIN; return at_command->id; } static int parse_csq(const char* string, int position, at_command_t* at_command) { /* CSQ action command - No parameter */ at_command->id = AT_CSQ; at_command->mask = AT_COMMAND_CSQ_MASK; return at_command->id; } static int parse_csq_test(const char* string, int position, at_command_t* at_command) { /* CSQ test command - No parameter */ at_command->id = AT_CSQ; return at_command->id; } static int parse_cesq(const char* string, int position, at_command_t* at_command) { /* CESQ action command - No parameter */ at_command->id = AT_CESQ; at_command->mask = AT_COMMAND_CESQ_MASK; return at_command->id; } static int parse_cesq_test(const char* string, int position, at_command_t* at_command) { /* CESQ test command - No parameter */ at_command->id = AT_CESQ; return at_command->id; } static int parse_clac(const char* string, int position, at_command_t* at_command) { /* CLAC action command - No parameter */ at_command->id = AT_CLAC; at_command->mask = AT_COMMAND_CLAC_MASK; return at_command->id; } static int parse_clac_test(const char* string, int position, at_command_t* at_command) { /* CLAC test command - No parameter */ at_command->id = AT_CLAC; return at_command->id; } static int parse_cmee_set(const char* string, int position, at_command_t* at_command) { /* CMEE parameter command - Parameter [] */ at_command->id = AT_CMEE; unsigned char* parameter_start_index = (unsigned char*) string + position; /* Check the number of parameters */ unsigned number_of_parameters = NumberOfParameters(parameter_start_index); /* Parse the parameters */ switch (number_of_parameters) { case 0: // No any parameter LOG_TRACE(INFO, "USR-API - Parsing of AT+CMEE= command succeed"); at_command->mask = AT_COMMAND_NO_PARAM; break; case 1: // Only parameter is present if (ParseCommand(parameter_start_index, "@i", &at_command->command.cmee.n) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CMEE= failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CMEE= command succeed (n:%d)", at_command->command.cmee.n); at_command->mask = AT_CMEE_N_MASK; break; default: LOG_TRACE(ERROR, "USR-API - Invalid number of parameters (%d)", number_of_parameters); return RETURNerror; } return at_command->id; } static int parse_cmee_get(const char* string, int position, at_command_t* at_command) { /* CMEE read command - No parameter */ at_command->id = AT_CMEE; return at_command->id; } static int parse_cmee_test(const char* string, int position, at_command_t* at_command) { /* CMEE test command - No parameter */ at_command->id = AT_CMEE; return at_command->id; } static int parse_cnum(const char* string, int position, at_command_t* at_command) { /* CNUM action command - No parameter */ at_command->id = AT_CNUM; at_command->mask = AT_COMMAND_CNUM_MASK; return at_command->id; } static int parse_cnum_test(const char* string, int position, at_command_t* at_command) { /* CNUM test command - No parameter */ at_command->id = AT_CNUM; return at_command->id; } static int parse_clck_set(const char* string, int position, at_command_t* at_command) { /* CLCK action command - Parameters ,[,] */ at_command->id = AT_CLCK; unsigned char* parameter_start_index = (unsigned char*) string + position; /* Check the number of parameters */ unsigned number_of_parameters = NumberOfParameters(parameter_start_index); switch (number_of_parameters) { case 2: // , parameters are present if (ParseCommand(parameter_start_index, "@r,@i", &at_command->command.clck.fac, AT_CLCK_FAC_SIZE, &at_command->command.clck.mode) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CLCK=, " "failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CLCK=, " "succeed (fac:%s, mode:%d)", at_command->command.clck.fac, at_command->command.clck.mode); at_command->mask = AT_COMMAND_NO_PARAM; break; case 3: // ,, parameters are present if (ParseCommand(parameter_start_index, "@r,@i,@r", &at_command->command.clck.fac, AT_CLCK_FAC_SIZE, &at_command->command.clck.mode, &at_command->command.clck.passwd, AT_CLCK_PASSWD_SIZE) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CLCK=," " failed"); return RETURNerror; } if (!IsNumeric(at_command->command.clck.passwd,AT_CLCK_PASSWD_SIZE)) { LOG_TRACE(ERROR, "USR-API - Incoming parameter is not a valid password!"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CLCK=," " succeed (fac:%s, mode:%d, passwd:%s)", at_command->command.clck.fac, at_command->command.clck.mode, at_command->command.clck.passwd); at_command->mask = AT_CLCK_PASSWD_MASK; break; default: LOG_TRACE(ERROR, "USR-API - Invalid number of parameters (%d)", number_of_parameters); return -1; } return at_command->id; } static int parse_clck_test(const char* string, int position, at_command_t* at_command) { /* CLCK test command - No parameter */ at_command->id = AT_CLCK; return at_command->id; } static int parse_cops_set(const char* string, int position, at_command_t* at_command) { /* COPS parameter command - Parameters [[,[,[,]]]] */ at_command->id = AT_COPS; unsigned char* parameter_start_index = (unsigned char*) string + position; /* Check the number of parameters */ unsigned number_of_parameters = NumberOfParameters(parameter_start_index); /* Parse the parameters */ char oper_value[AT_COPS_NUM_SIZE]; switch (number_of_parameters) { case 0: // No any parameter LOG_TRACE(INFO, "USR-API - Parsing of AT+COPS= command succeed"); at_command->mask = AT_COMMAND_NO_PARAM; break; case 1: // Only parameter is present if (ParseCommand(parameter_start_index, "@i", &at_command->command.cops.mode) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+COPS= command failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+COPS= command succeed (mode:%d)", at_command->command.cops.mode); at_command->mask = AT_COPS_MODE_MASK; break; case 2: // , parameters are present if (ParseCommand(parameter_start_index, "@i,@i", &at_command->command.cops.mode, &at_command->command.cops.format) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+COPS=, command failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+COPS=, command succeed (mode:%d, format:%d)", at_command->command.cops.mode, at_command->command.cops.format); at_command->mask = AT_COPS_MODE_MASK | AT_COPS_FORMAT_MASK; break; case 3: // ,, parameters are present if (ParseCommand(parameter_start_index, "@i,@i,@r", &at_command->command.cops.mode, &at_command->command.cops.format, oper_value, NET_FORMAT_MAX_SIZE) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+COPS=,, command failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+COPS=,, command succeed (mode:%d, format:%d)", at_command->command.cops.mode, at_command->command.cops.format); /* Now, process parameter according to the specified parameter */ switch (at_command->command.cops.format) { case AT_COPS_LONG: /* long format alphanumeric */ strncpy((char*) at_command->command.cops.plmn.id.alpha_long, oper_value, AT_COPS_LONG_SIZE); LOG_TRACE(INFO, "USR-API - parameter's value is '%s'", at_command->command.cops.plmn.id.alpha_long); break; case AT_COPS_SHORT: /* short format alphanumeric */ strncpy((char*) at_command->command.cops.plmn.id.alpha_short, oper_value, AT_COPS_SHORT_SIZE); LOG_TRACE(INFO, "USR-API - parameter's value is '%s'", at_command->command.cops.plmn.id.alpha_short); break; case AT_COPS_NUM: /* numeric */ strncpy((char*) at_command->command.cops.plmn.id.num, oper_value, AT_COPS_NUM_SIZE); LOG_TRACE(INFO, "USR-API - parameter's value is '%s'", at_command->command.cops.plmn.id.num); break; default: LOG_TRACE(ERROR, "USR-API - Invalid format value (%d)", at_command->command.cops.format); return RETURNerror; } at_command->mask = AT_COPS_MODE_MASK | AT_COPS_FORMAT_MASK | AT_COPS_OPER_MASK; break; case 4: // ,,, parameters are present if (ParseCommand(parameter_start_index, "@i,@i,@0", &at_command->command.cops.mode, &at_command->command.cops.format) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+COPS=, command failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+COPS=,, command succeed (mode:%d, format:%d)", at_command->command.cops.mode, at_command->command.cops.format); /* Now, process parameter according to the specified parameter */ switch (at_command->command.cops.format) { case AT_COPS_LONG: /* long format alphanumeric */ if (ParseCommand(parameter_start_index, "@i,@i,@r,@i", &at_command->command.cops.mode, &at_command->command.cops.format, oper_value, AT_COPS_LONG_SIZE, &at_command->command.cops.AcT) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+COPS=,,, command failed"); return RETURNerror; } strncpy((char*) at_command->command.cops.plmn.id.alpha_long, oper_value, AT_COPS_LONG_SIZE); LOG_TRACE(INFO, "USR-API - Parsing of AT+COPS=,,, command succeed (oper:%s, Act:%d)", at_command->command.cops.plmn.id.alpha_long, at_command->command.cops.AcT); break; case AT_COPS_SHORT: /* short format alphanumeric */ if (ParseCommand(parameter_start_index, "@i,@i,@r,@i", &at_command->command.cops.mode, &at_command->command.cops.format, oper_value, AT_COPS_SHORT_SIZE, &at_command->command.cops.AcT) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+COPS=,,, command failed"); return RETURNerror; } strncpy((char*) at_command->command.cops.plmn.id.alpha_short, oper_value, AT_COPS_SHORT_SIZE); LOG_TRACE(INFO, "USR-API - Parsing of AT+COPS=,,, command succeed (oper:%s, Act:%d)", at_command->command.cops.plmn.id.alpha_short, at_command->command.cops.AcT); break; case AT_COPS_NUM: /* numeric */ if (ParseCommand(parameter_start_index, "@i,@i,@r,@i", &at_command->command.cops.mode, &at_command->command.cops.format, oper_value, AT_COPS_NUM_SIZE, &at_command->command.cops.AcT) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+COPS=,,, command failed"); return RETURNerror; } strncpy((char*) at_command->command.cops.plmn.id.num, oper_value, AT_COPS_NUM_SIZE); LOG_TRACE(INFO, "USR-API - Parsing of AT+COPS=,,, command succeed (oper:%s, Act:%d)", at_command->command.cops.plmn.id.num, at_command->command.cops.AcT); break; default: LOG_TRACE(ERROR, "USR-API - Invalid format value (%d)", at_command->command.cops.format); return RETURNerror; } at_command->mask = AT_COPS_MODE_MASK | AT_COPS_FORMAT_MASK | AT_COPS_OPER_MASK | AT_COPS_ACT_MASK; break; default: LOG_TRACE(ERROR, "USR-API - Invalid number of parameters (%d)", number_of_parameters); return RETURNerror; } return at_command->id; } static int parse_cops_get(const char* string, int position, at_command_t* at_command) { /* COPS test command - No parameter */ at_command->id = AT_COPS; return at_command->id; } static int parse_cops_test(const char* string, int position, at_command_t* at_command) { /* COPS test command - No parameter */ at_command->id = AT_COPS; return at_command->id; } static int parse_creg_set(const char* string, int position, at_command_t* at_command) { /* CREG parameter command - Parameter [] */ at_command->id = AT_CREG; unsigned char* parameter_start_index = (unsigned char*) string + position; /* Check the number of parameters */ unsigned number_of_parameters = NumberOfParameters(parameter_start_index); /* Parse the parameters */ switch (number_of_parameters) { case 0: // No any parameter LOG_TRACE(INFO, "USR-API - Parsing of AT+CREG= command succeed"); at_command->mask = AT_COMMAND_NO_PARAM; break; case 1: // Only parameter is present if (ParseCommand(parameter_start_index, "@i", &at_command->command.creg.n) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CREG= failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CREG= command succeed (n:%d)", at_command->command.creg.n); at_command->mask = AT_CREG_N_MASK; break; default: LOG_TRACE(ERROR, "USR-API - Invalid number of parameters (%d)", number_of_parameters); return RETURNerror; } return at_command->id; } static int parse_creg_get(const char* string, int position, at_command_t* at_command) { /* CREG read command - No parameter */ at_command->id = AT_CREG; return at_command->id; } static int parse_creg_test(const char* string, int position, at_command_t* at_command) { /* CREG test command - No parameter */ at_command->id = AT_CREG; return at_command->id; } static int parse_cgatt_set(const char* string, int position, at_command_t* at_command) { /* CGATT parameter command - Parameter [] */ at_command->id = AT_CGATT; unsigned char* parameter_start_index = (unsigned char*) string + position; /* Check the number of parameters */ unsigned number_of_parameters = NumberOfParameters(parameter_start_index); /* Parse the parameters */ switch (number_of_parameters) { case 0: // No any parameter LOG_TRACE(INFO, "USR-API - Parsing of AT+CGATT= command succeed"); at_command->mask = AT_COMMAND_NO_PARAM; break; case 1: // Only parameter is present if (ParseCommand(parameter_start_index, "@i", &at_command->command.cgatt.state) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CGATT= failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CGATT= command succeed (state:%d)", at_command->command.cgatt.state); at_command->mask = AT_CGATT_STATE_MASK; break; default: LOG_TRACE(ERROR, "USR-API - Invalid number of parameters (%d)", number_of_parameters); return RETURNerror; } return at_command->id; } static int parse_cgatt_get(const char* string, int position, at_command_t* at_command) { /* CGATT read command - No parameter */ at_command->id = AT_CGATT; return at_command->id; } static int parse_cgatt_test(const char* string, int position, at_command_t* at_command) { /* CGATT test command - No parameter */ at_command->id = AT_CGATT; return at_command->id; } static int parse_cgreg_set(const char* string, int position, at_command_t* at_command) { /* CGREG parameter command - Parameter [] */ at_command->id = AT_CGREG; unsigned char* parameter_start_index = (unsigned char*) string + position; /* Check the number of parameters */ unsigned number_of_parameters = NumberOfParameters(parameter_start_index); /* Parse the parameters */ switch (number_of_parameters) { case 0: // No any parameter LOG_TRACE(INFO, "USR-API - Parsing of AT+CGREG= command succeed"); at_command->mask = AT_COMMAND_NO_PARAM; break; case 1: // Only parameter is present if (ParseCommand(parameter_start_index, "@i", &at_command->command.cgreg.n) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CGREG= failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CGREG= command succeed (n:%d)", at_command->command.cgreg.n); at_command->mask = AT_CGREG_N_MASK; break; default: LOG_TRACE(ERROR, "USR-API - Invalid number of parameters (%d)", number_of_parameters); return RETURNerror; } return at_command->id; } static int parse_cgreg_get(const char* string, int position, at_command_t* at_command) { /* CGREG read command - No parameter */ at_command->id = AT_CGREG; return at_command->id; } static int parse_cgreg_test(const char* string, int position, at_command_t* at_command) { /* CGREG test command - No parameter */ at_command->id = AT_CGREG; return at_command->id; } static int parse_cereg_set(const char* string, int position, at_command_t* at_command) { /* CEREG parameter command - Parameter [] */ at_command->id = AT_CEREG; unsigned char* parameter_start_index = (unsigned char*) string + position; /* Check the number of parameters */ unsigned number_of_parameters = NumberOfParameters(parameter_start_index); /* Parse the parameters */ switch (number_of_parameters) { case 0: // No any parameter LOG_TRACE(INFO, "USR-API - Parsing of AT+CEREG= command succeed"); at_command->mask = AT_COMMAND_NO_PARAM; break; case 1: // Only parameter is present if (ParseCommand(parameter_start_index, "@i", &at_command->command.cereg.n) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CEREG= failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CEREG= command succeed (n:%d)", at_command->command.cereg.n); at_command->mask = AT_CEREG_N_MASK; break; default: LOG_TRACE(ERROR, "USR-API - Invalid number of parameters (%d)", number_of_parameters); return RETURNerror; } return at_command->id; } static int parse_cereg_get(const char* string, int position, at_command_t* at_command) { /* CEREG read command - No parameter */ at_command->id = AT_CEREG; return at_command->id; } static int parse_cereg_test(const char* string, int position, at_command_t* at_command) { /* CEREG test command - No parameter */ at_command->id = AT_CEREG; return at_command->id; } static int parse_cgdcont_set(const char* string, int position, at_command_t* at_command) { /* CGDCONT parameter command - Parameters [[,[,[,[,[,[,[,[,[,]]]]]]]]]] */ at_command->id = AT_CGDCONT; unsigned char* parameter_start_index = (unsigned char*) string + position; /* Check the number of parameters */ unsigned number_of_parameters = NumberOfParameters(parameter_start_index); /* Parse the parameters */ switch (number_of_parameters) { case 1: // Only parameter is present if (ParseCommand(parameter_start_index, "@i", &at_command->command.cgdcont.cid) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CGDCONT= failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CGDCONT= command succeed (cid:%d)", at_command->command.cgdcont.cid); at_command->mask = AT_CGDCONT_CID_MASK; break; case 2: // , parameters are present if (ParseCommand(parameter_start_index, "@i,@r", &at_command->command.cgdcont.cid, &at_command->command.cgdcont.PDP_type, AT_CGDCONT_PDP_SIZE) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CGDCONT=, failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CGDCONT=, succeed (cid:%d, pdp_type:%s)", at_command->command.cgdcont.cid, at_command->command.cgdcont.PDP_type); at_command->mask = AT_CGDCONT_CID_MASK | AT_CGDCONT_PDP_TYPE_MASK; break; case 3: // ,, parameters are present if (ParseCommand(parameter_start_index, "@i,@r,@r", &at_command->command.cgdcont.cid, &at_command->command.cgdcont.PDP_type, AT_CGDCONT_PDP_SIZE, &at_command->command.cgdcont.APN, AT_CGDCONT_APN_SIZE) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CGDCONT=,, failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CGDCONT=,, succeed (cid:%d, pdp_type:%s, apn:%s)", at_command->command.cgdcont.cid, at_command->command.cgdcont.PDP_type, at_command->command.cgdcont.APN); at_command->mask = AT_CGDCONT_CID_MASK | AT_CGDCONT_PDP_TYPE_MASK | AT_CGDCONT_APN_MASK; break; case 4: // ,,, parameters are present if (ParseCommand(parameter_start_index, "@i,@r,@r,@r", &at_command->command.cgdcont.cid, &at_command->command.cgdcont.PDP_type, AT_CGDCONT_PDP_SIZE, &at_command->command.cgdcont.APN, AT_CGDCONT_APN_SIZE, &at_command->command.cgdcont.PDP_addr, AT_CGDCONT_ADDR_SIZE) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CGDCONT=,,, failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CGDCONT=,,, succeed (cid:%d, pdp_type:%s, apn:%s, pdp_addr:%s)", at_command->command.cgdcont.cid, at_command->command.cgdcont.PDP_type, at_command->command.cgdcont.APN, at_command->command.cgdcont.PDP_addr); at_command->mask = AT_CGDCONT_CID_MASK | AT_CGDCONT_PDP_TYPE_MASK | AT_CGDCONT_APN_MASK | AT_CGDCONT_PDP_ADDR_MASK; break; case 5: // ,,,, parameters are present if (ParseCommand(parameter_start_index, "@i,@r,@r,@r,@i", &at_command->command.cgdcont.cid, &at_command->command.cgdcont.PDP_type, AT_CGDCONT_PDP_SIZE, &at_command->command.cgdcont.APN, AT_CGDCONT_APN_SIZE, &at_command->command.cgdcont.PDP_addr, AT_CGDCONT_ADDR_SIZE, &at_command->command.cgdcont.d_comp) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CGDCONT=,,,, failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CGDCONT=,,,, succeed (cid:%d, pdp_type:%s, apn:%s, pdp_addr:%s, d_comp:%d)", at_command->command.cgdcont.cid, at_command->command.cgdcont.PDP_type, at_command->command.cgdcont.APN, at_command->command.cgdcont.PDP_addr, at_command->command.cgdcont.d_comp); at_command->mask = AT_CGDCONT_CID_MASK | AT_CGDCONT_PDP_TYPE_MASK | AT_CGDCONT_APN_MASK | AT_CGDCONT_PDP_ADDR_MASK | AT_CGDCONT_D_COMP_MASK; break; case 6: // ,,,,, parameters are present if (ParseCommand(parameter_start_index, "@i,@r,@r,@r,@i,@i", &at_command->command.cgdcont.cid, &at_command->command.cgdcont.PDP_type, AT_CGDCONT_PDP_SIZE, &at_command->command.cgdcont.APN, AT_CGDCONT_APN_SIZE, &at_command->command.cgdcont.PDP_addr, AT_CGDCONT_ADDR_SIZE, &at_command->command.cgdcont.d_comp, &at_command->command.cgdcont.h_comp) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CGDCONT=,,,,, failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CGDCONT=,,,,, succeed (cid:%d, pdp_type:%s, apn:%s, pdp_addr:%s, d_comp:%d, h_comp:%d)", at_command->command.cgdcont.cid, at_command->command.cgdcont.PDP_type, at_command->command.cgdcont.APN, at_command->command.cgdcont.PDP_addr, at_command->command.cgdcont.d_comp, at_command->command.cgdcont.h_comp); at_command->mask = AT_CGDCONT_CID_MASK | AT_CGDCONT_PDP_TYPE_MASK | AT_CGDCONT_APN_MASK | AT_CGDCONT_PDP_ADDR_MASK | AT_CGDCONT_D_COMP_MASK | AT_CGDCONT_H_COMP_MASK; break; case 7: // ,,,,,, parameters are present if (ParseCommand(parameter_start_index, "@i,@r,@r,@r,@i,@i,@i", &at_command->command.cgdcont.cid, &at_command->command.cgdcont.PDP_type, AT_CGDCONT_PDP_SIZE, &at_command->command.cgdcont.APN, AT_CGDCONT_APN_SIZE, &at_command->command.cgdcont.PDP_addr, AT_CGDCONT_ADDR_SIZE, &at_command->command.cgdcont.d_comp, &at_command->command.cgdcont.h_comp, &at_command->command.cgdcont.IPv4AddrAlloc) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CGDCONT=,,,,,, failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CGDCONT=,,,,,, succeed (cid:%d, pdp_type:%s, apn:%s, pdp_addr:%s, d_comp:%d, h_comp:%d, ipv4addralloc:%d)", at_command->command.cgdcont.cid, at_command->command.cgdcont.PDP_type, at_command->command.cgdcont.APN, at_command->command.cgdcont.PDP_addr, at_command->command.cgdcont.d_comp, at_command->command.cgdcont.h_comp, at_command->command.cgdcont.IPv4AddrAlloc); at_command->mask = AT_CGDCONT_CID_MASK | AT_CGDCONT_PDP_TYPE_MASK | AT_CGDCONT_APN_MASK | AT_CGDCONT_PDP_ADDR_MASK | AT_CGDCONT_D_COMP_MASK | AT_CGDCONT_H_COMP_MASK | AT_CGDCONT_IPV4ADDRALLOC_MASK; break; case 8: // ,,,,,,, parameters are present if (ParseCommand(parameter_start_index, "@i,@r,@r,@r,@i,@i,@i,@i", &at_command->command.cgdcont.cid, &at_command->command.cgdcont.PDP_type, AT_CGDCONT_PDP_SIZE, &at_command->command.cgdcont.APN, AT_CGDCONT_APN_SIZE, &at_command->command.cgdcont.PDP_addr, AT_CGDCONT_ADDR_SIZE, &at_command->command.cgdcont.d_comp, &at_command->command.cgdcont.h_comp, &at_command->command.cgdcont.IPv4AddrAlloc, &at_command->command.cgdcont.emergency_indication) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CGDCONT=,,,,,,, failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CGDCONT=,,,,,,, succeed (cid:%d, pdp_type:%s, apn:%s, pdp_addr:%s, d_comp:%d, h_comp:%d, ipv4addralloc:%d, emergency_indication:%d)", at_command->command.cgdcont.cid, at_command->command.cgdcont.PDP_type, at_command->command.cgdcont.APN, at_command->command.cgdcont.PDP_addr, at_command->command.cgdcont.d_comp, at_command->command.cgdcont.h_comp, at_command->command.cgdcont.IPv4AddrAlloc, at_command->command.cgdcont.emergency_indication); at_command->mask = AT_CGDCONT_CID_MASK | AT_CGDCONT_PDP_TYPE_MASK | AT_CGDCONT_APN_MASK | AT_CGDCONT_PDP_ADDR_MASK | AT_CGDCONT_D_COMP_MASK | AT_CGDCONT_H_COMP_MASK | AT_CGDCONT_IPV4ADDRALLOC_MASK | AT_CGDCONT_EMERGECY_INDICATION_MASK; break; case 9: /* ,,,,,, * ,, * parameters are present */ if (ParseCommand(parameter_start_index, "@i,@r,@r,@r,@i,@i,@i,@i,@i", &at_command->command.cgdcont.cid, &at_command->command.cgdcont.PDP_type, AT_CGDCONT_PDP_SIZE, &at_command->command.cgdcont.APN, AT_CGDCONT_APN_SIZE, &at_command->command.cgdcont.PDP_addr, AT_CGDCONT_ADDR_SIZE, &at_command->command.cgdcont.d_comp, &at_command->command.cgdcont.h_comp, &at_command->command.cgdcont.IPv4AddrAlloc, &at_command->command.cgdcont.emergency_indication, &at_command->command.cgdcont.P_CSCF_discovery) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CGDCONT=,,,,,,,, failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CGDCONT=,,,,,,,, succeed (cid:%d, pdp_type:%s, apn:%s, pdp_addr:%s, d_comp:%d, h_comp:%d, ipv4addralloc:%d, emergency_indication:%d, p_cscf_discovery:%d)", at_command->command.cgdcont.cid, at_command->command.cgdcont.PDP_type, at_command->command.cgdcont.APN, at_command->command.cgdcont.PDP_addr, at_command->command.cgdcont.d_comp, at_command->command.cgdcont.h_comp, at_command->command.cgdcont.IPv4AddrAlloc, at_command->command.cgdcont.emergency_indication, at_command->command.cgdcont.P_CSCF_discovery); at_command->mask = AT_CGDCONT_CID_MASK | AT_CGDCONT_PDP_TYPE_MASK | AT_CGDCONT_APN_MASK | AT_CGDCONT_PDP_ADDR_MASK | AT_CGDCONT_D_COMP_MASK | AT_CGDCONT_H_COMP_MASK | AT_CGDCONT_IPV4ADDRALLOC_MASK | AT_CGDCONT_EMERGECY_INDICATION_MASK | AT_CGDCONT_P_CSCF_DISCOVERY_MASK; break; case 10: /* ,,,,,, * ,,, * parameters are present */ if (ParseCommand(parameter_start_index, "@i,@r,@r,@r,@i,@i,@i,@i,@i,@i", &at_command->command.cgdcont.cid, &at_command->command.cgdcont.PDP_type, AT_CGDCONT_PDP_SIZE, &at_command->command.cgdcont.APN, AT_CGDCONT_APN_SIZE, &at_command->command.cgdcont.PDP_addr, AT_CGDCONT_ADDR_SIZE, &at_command->command.cgdcont.d_comp, &at_command->command.cgdcont.h_comp, &at_command->command.cgdcont.IPv4AddrAlloc, &at_command->command.cgdcont.emergency_indication, &at_command->command.cgdcont.P_CSCF_discovery, &at_command->command.cgdcont.IM_CN_Signalling_Flag_Ind) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CGDCONT=,,,,,,,,, failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CGDCONT=,,,,,,,,, succeed (cid:%d, pdp_type:%s, apn:%s, pdp_addr:%s, d_comp:%d, h_comp:%d, ipv4addralloc:%d, emergency_indication:%d, p_cscf_discovery:%d, im_cn_signalling_flag:%d)", at_command->command.cgdcont.cid, at_command->command.cgdcont.PDP_type, at_command->command.cgdcont.APN, at_command->command.cgdcont.PDP_addr, at_command->command.cgdcont.d_comp, at_command->command.cgdcont.h_comp, at_command->command.cgdcont.IPv4AddrAlloc, at_command->command.cgdcont.emergency_indication, at_command->command.cgdcont.P_CSCF_discovery, at_command->command.cgdcont.IM_CN_Signalling_Flag_Ind); at_command->mask = AT_CGDCONT_CID_MASK | AT_CGDCONT_PDP_TYPE_MASK | AT_CGDCONT_APN_MASK | AT_CGDCONT_PDP_ADDR_MASK | AT_CGDCONT_D_COMP_MASK | AT_CGDCONT_H_COMP_MASK | AT_CGDCONT_IPV4ADDRALLOC_MASK | AT_CGDCONT_EMERGECY_INDICATION_MASK | AT_CGDCONT_P_CSCF_DISCOVERY_MASK | AT_CGDCONT_IM_CN_SIGNALLING_FLAG_IND_MASK; break; default: LOG_TRACE(ERROR, "USR-API - Invalid number of parameters (%d)", number_of_parameters); return RETURNerror; } return at_command->id; } static int parse_cgdcont_get(const char* string, int position, at_command_t* at_command) { /* CGDCONT read command - No parameter */ at_command->id = AT_CGDCONT; return at_command->id; } static int parse_cgdcont_test(const char* string, int position, at_command_t* at_command) { /* CGDCONT test command - No parameter */ at_command->id = AT_CGDCONT; return at_command->id; } static int parse_cgact_set(const char* string, int position, at_command_t* at_command) { /* CGACT parameter command - Parameters [,] */ at_command->id = AT_CGACT; unsigned char* parameter_start_index = (unsigned char*) string + position; /* Check the number of parameters */ unsigned number_of_parameters = NumberOfParameters(parameter_start_index); switch (number_of_parameters) { case 1: // Only parameter is present if (ParseCommand(parameter_start_index, "@i", &at_command->command.cgact.state) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CGACT= failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CGACT= succeed (state:%d)", at_command->command.cgact.state); at_command->mask = AT_CGACT_STATE_MASK; break; case 2: // , parameters are present if (ParseCommand(parameter_start_index, "@i,@i", &at_command->command.cgact.state, &at_command->command.cgact.cid) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CGACT=, failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CGACT=, succeed (state:%d, cid:%d)", at_command->command.cgact.state, at_command->command.cgact.cid); at_command->mask = AT_CGACT_STATE_MASK | AT_CGACT_CID_MASK; break; default: LOG_TRACE(ERROR, "USR-API - Invalid number of parameters (%d)", number_of_parameters); return -1; } return at_command->id; } static int parse_cgact_get(const char* string, int position, at_command_t* at_command) { /* CGACT read command - No parameter */ at_command->id = AT_CGACT; return at_command->id; } static int parse_cgact_test(const char* string, int position, at_command_t* at_command) { /* CGACT test command - No parameter */ at_command->id = AT_CGACT; return at_command->id; } static int parse_cgpaddr_set(const char* string, int position, at_command_t* at_command) { /* CGPADDR parameter command - Parameters [] */ at_command->id = AT_CGPADDR; unsigned char* parameter_start_index = (unsigned char*) string + position; /* Check the number of parameters */ unsigned number_of_parameters = NumberOfParameters(parameter_start_index); switch (number_of_parameters) { case 0: // No any parameter LOG_TRACE(INFO, "USR-API - Parsing of AT+CGPADDR= command succeed"); at_command->mask = AT_COMMAND_NO_PARAM; break; case 1: // Only parameter is present if (ParseCommand(parameter_start_index, "@i", &at_command->command.cgpaddr.cid) != RETURNok) { LOG_TRACE(ERROR, "USR-API - Parsing of AT+CGPADDR= failed"); return RETURNerror; } LOG_TRACE(INFO, "USR-API - Parsing of AT+CGPADDR= succeed (cid:%d)", at_command->command.cgpaddr.cid); at_command->mask = AT_CGPADDR_CID_MASK; break; default: LOG_TRACE(ERROR, "USR-API - Invalid number of parameters (%d)", number_of_parameters); return -1; } return at_command->id; } static int parse_cgpaddr_test(const char* string, int position, at_command_t* at_command) { /* CGPADDR test command - No parameter */ at_command->id = AT_CGPADDR; return at_command->id; }