FreeCalypso > hg > fc-magnetite
view src/g23m-aci/aci/ati_prs.c @ 347:78d1df0b8487
aci2: AT%CBC and AT@CHARGE implemented
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 16 Dec 2017 00:37:43 +0000 |
parents | 53929b40109c |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : GSM-F&D (8411) | Modul : ATI +----------------------------------------------------------------------------- | Copyright 2002 Texas Instruments Berlin, AG | All rights reserved. | | This file is confidential and a trade secret of Texas | Instruments Berlin, AG | The receipt of or possession of this file does not convey | any rights to reproduce or disclose its contents or to | manufacture, use, or sell anything it may describe, in | whole, or in part, without the specific written consent of | Texas Instruments Berlin, AG. +----------------------------------------------------------------------------- | Purpose : AT Command parameter parser +----------------------------------------------------------------------------- */ #ifndef ATI_PRS_C #define ATI_PRS_C #include "aci_all.h" #include <stdio.h> #include <stdarg.h> #include <ctype.h> #include "aci_cmh.h" #include "ati_cmd.h" #include "aci_cmd.h" #include "aci_prs.h" #ifdef GPRS #include "gaci_cmh.h" #endif /* GPRS */ #include "aci_lst.h" #include "ati_int.h" #ifdef OPTION_RELATIVE LOCAL ULONG offset; #endif static UBYTE parse_index = 0; /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : ACI_PRS | | STATE : code ROUTINE : parseBin | +--------------------------------------------------------------------+ PURPOSE : parse binary value */ GLOBAL char *parseBin (int digits, char *b, SHORT *i) { int found = 0; *i = 0; while (digits-- AND *b >= '0' AND *b <= '1') { found++; *i *= 2; *i += *b - '0'; b++; } return ((found) ? b : 0); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : ACI_PRS | | STATE : code ROUTINE : parseHex | +--------------------------------------------------------------------+ PURPOSE : parse hexadecimal value */ GLOBAL char *parseHex (int digits, char *b, UBYTE *i) { int found = 0; *i = 0; while (digits-- AND ((*b >= '0' AND *b <= '9') OR (*b >= 'a' AND *b <= 'f') OR (*b >= 'A' AND *b <= 'F'))) { found++; *i *= 16; if (*b >= '0' AND *b <= '9') *i += *b - '0'; if (*b >= 'a' AND *b <= 'f') *i += *b - 'a' + 10; if (*b >= 'A' AND *b <= 'F') *i += *b - 'A' + 10; b++; } return ((found AND found <= 2) ? b : 0); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : ACI_PRS | | STATE : code ROUTINE : parseHexToLong | +--------------------------------------------------------------------+ PURPOSE : parse hexadecimal value */ GLOBAL char *parseHexToLong (int digits, char *b, LONG *i) { *i = 0; while (digits-- AND ((*b >= '0' AND *b <= '9') OR (*b >= 'a' AND *b <= 'f') OR (*b >= 'A' AND *b <= 'F'))) { *i *= 16; if (*b >= '0' AND *b <= '9') *i += *b - '0'; if (*b >= 'a' AND *b <= 'f') *i += *b - 'a' + 10; if (*b >= 'A' AND *b <= 'F') *i += *b - 'A' + 10; b++; } return ( digits EQ 0 ? 0 : b ); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : ACI_PRS | | STATE : code ROUTINE : parseEnum | +--------------------------------------------------------------------+ PURPOSE : parse enum value */ GLOBAL char *parseEnum (int digits, char *b, int *i) { int found = 0; *i = 0; while (digits-- AND *b >= '0' AND *b <= '9') { found++; *i *= 10; *i += *b - '0'; b++; } return ((found) ? b : 0); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : ACI_PRS | | STATE : code ROUTINE : parseShort | +--------------------------------------------------------------------+ PURPOSE : parse Short value */ GLOBAL char *parseShort (int digits, char *b, SHORT *i) { int found = 0; *i = 0; while (digits-- AND *b >= '0' AND *b <= '9') { found++; *i *= 10; *i += *b - '0'; b++; } return ((found) ? b : 0); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : ACI_PRS | | STATE : code ROUTINE : parseStr | +--------------------------------------------------------------------+ PURPOSE : parse string value */ GLOBAL char *parseStr (int digits, char *b, char *s) { int found = 0; *s = 0; if (*b NEQ '"') return 0; b++; while (digits-- AND *b AND *b >= 0x20) { found++; if (*b EQ '"') { *s = 0; b++; break; } if (*b EQ '\\') { b = parseHex(2,b+1,(UBYTE *) s); /* ES!! ZERO ? */ if (!b) return 0; s++; } else *s++ = *b++; } if(*(b-1) NEQ '"') return 0; *s = 0; /* zero terminated */ return ((found) ? b : 0); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : ACI_PRS | | STATE : code ROUTINE : parseZStr | +--------------------------------------------------------------------+ PURPOSE : parse string value */ GLOBAL char *parseZStr (int digits, char *b, char *s) { int found = 0; *s = 0; if (*b NEQ '"') return 0; b++; while (digits--) { found++; if (*b EQ '"') { *s = 0; b++; break; } if (*b EQ '\\') { b = parseHex(2,b+1,(UBYTE *) s); /* ES!! ZERO ? */ if (!b) return 0; s++; } else *s++ = *b++; } if(*(b-1) NEQ '"') return 0; *s = 0; /* zero terminated */ return ((found) ? b : 0); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : ACI_PRS | | STATE : code ROUTINE : parseNStr | +--------------------------------------------------------------------+ PURPOSE : parse string value and if not numeric returns error */ GLOBAL char *parseNStr (int digits, char *b, char *s) { int found = 0; *s = 0; if (*b NEQ '"') return 0; b++; while (digits-- AND *b AND *b >= 0x20) { found++; if (*b EQ '"') { *s = 0; b++; break; } if (*b EQ '\\') { b = parseHex(2,b+1,(UBYTE *) s); /* ES!! ZERO ? */ if (!b) return 0; s++; } if ( *b > '9' OR *b < '0') return 0; /*check if numeric value*/ else *s++ = *b++; } if(*(b-1) NEQ '"') return 0; *s = 0; /* zero terminated */ return ((found) ? b : 0); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : ACI_PRS | | STATE : code ROUTINE : parseASCII | +--------------------------------------------------------------------+ PURPOSE : parse ASCII value */ GLOBAL char *parseASCII (int digits, char *b, char *i) { int found = 0; *i = 0; while (digits-- AND *b NEQ ' ' AND *b NEQ ',' AND *b NEQ ';' ) { found++; *i = *b; i++; b++; } return ((found) ? b : 0); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : ACI_PRS | | STATE : code ROUTINE : parseQASCII | +--------------------------------------------------------------------+ PURPOSE : parse ASCII value and terminate with 0 */ GLOBAL char *parseQASCII (int digits, char *b, char *i) { int found = 0; *i = 0; while (digits-- AND *b NEQ ',' AND *b NEQ ';' AND *b NEQ '\0') { found++; *i = *b; i++; b++; } if (found) { *i = 0; return (b); } return (NULL); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : ACI_PRS | | STATE : code ROUTINE : parseStrLen | +--------------------------------------------------------------------+ PURPOSE : parse sting, return length and startpoint */ GLOBAL char *parseStrLen (USHORT *len, char *b, char **p) { *len = 0; if( *b EQ '"' ) b++; /* Check if the string is a null string like "" */ if( *b EQ '"' ) { b++; /* return new buffer position without setting p, thereby omitting the parameter */ return b; } *p = b; while ( *b NEQ '\0' AND *b NEQ ',' AND *b NEQ ';' AND *b NEQ '"' ) { (*len)++; b++; } if(*b EQ '"') { b++; } return ((*len) ? b : 0); } #ifdef GPRS /* +--------------------------------------------------------------------+ | PROJECT : UMTS MODULE : ACI_PRS | | STATE : devellopment ROUTINE : parseExpo | +--------------------------------------------------------------------+ PURPOSE : parse exponential expresion (ex. 2E3) */ GLOBAL char *parseExpo( int digits, char *b, T_PS_ber *e ) { BOOL valid = FALSE; e->ratio_mant = 0; e->ratio_exp = 0; if( *b EQ '"' ) /* start of string */ { b++; while( digits-- AND *b >= '0' AND *b <= '9' ) { e->ratio_mant *= 10; e->ratio_mant += *b - '0'; b++; } if( *b EQ 'E' ) { b++; while( digits-- AND *b >= '0' AND *b <= '9' ) { e->ratio_exp *= 10; e->ratio_exp += *b - '0'; b++; valid = TRUE; } if( *b EQ '"' ) /* end of string */ { b++; } else { valid = FALSE; } } else { valid = FALSE; } } else { valid = FALSE; } return ((valid) ? b : 0); } /* END parseExpo(...) */ /* +--------------------------------------------------------------------+ | PROJECT : UMTS MODULE : ACI_PRS | | STATE : Finished ROUTINE : parseCid_list | +--------------------------------------------------------------------+ PURPOSE : Parse a list of Cids. If the parsing is sucessfull the number of parsed cids is returned otherwise -1 is returned. */ GLOBAL char *parseCid_list(char *b, U8 *cid_list_length, U8 *cid_list) { U8 no_of_cids; char *end; /* Parse all cids into the cid_list */ no_of_cids = 0; do { /* If it's not the first cid remove the "," */ if( no_of_cids ) b++; /* Set the entry to omitted. */ cid_list[no_of_cids] = PDP_CONTEXT_CID_OMITTED; /* Parse the value */ cid_list[no_of_cids] = (U8) strtol( b, &end, 10 ); b = end; /* If a cid is omitted no cids must be specified at all. */ if( cid_list[no_of_cids] EQ PDP_CONTEXT_CID_OMITTED ) { if( no_of_cids NEQ 0 ) { /* Don't accept omitted cids inside if it's not the first (ex. 1,,2,3 is not allowed). */ cmdCmeError( CME_ERR_OpNotSupp ); return( NULL ); } /* Break the while */ break; } if( (!b) OR (cid_list[no_of_cids] < PDP_CONTEXT_CID_MIN) OR (cid_list[no_of_cids] > PDP_CONTEXT_CID_MAX) OR (no_of_cids >= PDP_CONTEXT_CID_MAX) ) { cmdCmeError( CME_ERR_OpNotSupp ); return( NULL ); } no_of_cids++; } while( *b EQ ',' AND no_of_cids < *cid_list_length ); cid_list[no_of_cids+1] = PDP_CONTEXT_CID_INVALID; *cid_list_length = no_of_cids; return( b ); } #endif /* GPRS */ /* +----------------------------------------------------------------------+ | PROJECT : UMTS MODULE : ATI_PRS | | STATE : - ROUTINE : parsePointerToString | -----------------------------------------------------------------------+ PURPOSE : Parse pointer to input string. returns pointer to end of string. */ GLOBAL char *parsePointerToString(char chars, char *b, char **p_begin) { if( b AND *b EQ '"' ) { b++; *p_begin = b; while (chars-- AND *b AND *b NEQ '"') { b++; } if( *b EQ '"' ) { b++; } else { if( !chars ) { b = NULL; } } } return b; } /* +----------------------------------------------------------------------+ | PROJECT : UMTS MODULE : ATI_PRS | | STATE : - ROUTINE : StrToU16 | -----------------------------------------------------------------------+ PURPOSE : Parse string value to U16. */ char *StrToU16(char *p_str, U16 *p_result) { U32 val = 0; if( p_str ) { if( *p_str >= '0' AND *p_str <= '9' ) { while( *p_str >= '0' AND *p_str <= '9' ) { val *= 10; val += (int)(*p_str - '0'); p_str++; } } } if( val <= 0xffff ) /* 0xffff = max value of U16 */ *p_result = (U16)(val); else p_str = NULL; return p_str; } /* +---------------------------------------------------------------------+ | PROJECT : UMTS MODULE : ATI_PRS | | STATE : - ROUTINE : parseDSNP_U16 | ----------------------------------------------------------------------+ PURPOSE : parse dot-separated numeric parameters from the input string to an array of U8. ex. input p_in = "192.124.13.3" output p_out = {192,124,13,3} */ GLOBAL char *parseDSNP_U16( char blocks, char *p_in, U16 *p_out ) { if( p_in AND p_out ) { if( *p_in EQ '.' ) p_in++; while( blocks-- AND *p_in NEQ 0x00 ) { p_in = StrToU16(p_in, p_out); if( p_in AND blocks AND *p_in EQ '.' ) { p_in++; p_out++; } else break; } } return p_in; } /* +---------------------------------------------------------------------+ | PROJECT : UMTS MODULE : ATI_PRS | | STATE : - ROUTINE : parseIPv4Address | ----------------------------------------------------------------------+ */ GLOBAL char *parseIPv4Address(char *p_in, U8 * p_ip_addr, U8 * is_ip_valid) { U16 ip_addr[4]; char i; char *p_out = NULL; if( p_in AND p_ip_addr ) { p_out = parseDSNP_U16(4, p_in, ip_addr); for(i=0; i<4; i++) { if(ip_addr[i] <= 255) { p_ip_addr[i] = (U8) ip_addr[i]; } else { p_out = NULL; } } } * is_ip_valid = (p_out NEQ NULL); return p_out; } /* +---------------------------------------------------------------------+ | PROJECT : UMTS MODULE : ATI_PRS | | STATE : - ROUTINE : parseIPv6Address | ----------------------------------------------------------------------+ */ GLOBAL char *parseIPv6Address(char *p_in, U8 *p_ip_addr, U8 * is_ip_valid) { U16 ip_addr[16]; char i; char *p_out = NULL; if( p_in AND p_ip_addr ) { p_out = parseDSNP_U16(16, p_in, ip_addr); for(i=0; i<16; i++) { if(ip_addr[i] > 255) p_out = NULL; else p_ip_addr[i] = (U8) ip_addr[i]; } } * is_ip_valid = (p_out NEQ NULL); return p_out; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : ACI_PRS | | STATE : code ROUTINE : parse | +--------------------------------------------------------------------+ PURPOSE : parse AT command parameter */ GLOBAL char *parse (char *b, char *f, ...) { char fc; USHORT *i; #ifdef GPRS U8 *j; #endif /* GPRS */ LONG digits = -1; BOOL value_is_valid; /*lint -e516 -e10*/ va_list varpars; va_start (varpars, f); /* Initialize variable arguments. */ parse_index=0; while ((fc = *f++) NEQ 0) { parse_index++; /* Save the position of current parsing item */ value_is_valid = TRUE; if (islower(fc)) { if (*b EQ 0 OR *b EQ ';') { va_end (varpars); /* Reset variable arguments. */ return b; } if (*b EQ ',') { b++; value_is_valid = FALSE; } } switch (toupper(fc)) { case 'B': if (value_is_valid) b = parseBin(-1,b,va_arg (varpars, short*)); else (void)va_arg (varpars, short*); break; case 'X': if (value_is_valid) b = parseHex(-1,b,va_arg (varpars, unsigned char*)); else (void)va_arg (varpars, short*); break; case 'Y': if (value_is_valid) b = parseHexToLong(-1,b,va_arg (varpars, long*)); else (void)va_arg (varpars, short*); break; case 'D': if (value_is_valid) b = parseEnum(-1,b,va_arg (varpars, int*)); else (void)va_arg (varpars, int*); break; case 'R': if (value_is_valid) b = parseShort(-1,b,va_arg (varpars, short*)); else (void)va_arg (varpars, short*); break; case 'S': if (value_is_valid) { digits=va_arg (varpars, long); b = parseStr(digits,b,va_arg (varpars, char*)); } else { (void)va_arg (varpars, long); (void)va_arg (varpars, char*); } break; case 'N': if (value_is_valid) { digits=va_arg (varpars, long); b = parseNStr(digits,b,va_arg (varpars, char*)); } else { (void)va_arg (varpars, long); (void)va_arg (varpars, char*); } break; case 'Z': if (value_is_valid) { char* c = b; USHORT* plen = NULL; char* cmdPtr; USHORT cmdLen; digits = va_arg ( varpars, long ); cmdLen = va_arg ( varpars, unsigned ); cmdPtr = va_arg ( varpars, char* ); plen = va_arg ( varpars, unsigned short*); b = parseZStr ( MINIMUM (digits, cmdLen - ( b - cmdPtr )), b, va_arg ( varpars, char* ) ); if ( plen NEQ NULL ) { if ( b NEQ NULL ) *plen = b - c - 2; /* a string always includes two characters '"' */ else *plen = 0; } } else { (void)va_arg (varpars, long); (void)va_arg (varpars, unsigned short*); (void)va_arg (varpars, char*); } break; case 'A': if (value_is_valid) { digits=va_arg (varpars, long); b = parseASCII(digits,b,va_arg (varpars, char*)); } else { (void)va_arg (varpars, long); (void)va_arg (varpars, char*); } break; case 'Q': if (value_is_valid) { digits=va_arg (varpars, long); b = parseQASCII(digits,b,va_arg (varpars, char*)); } else { (void)va_arg (varpars, long); (void)va_arg (varpars, char*); } break; case 'L': if (value_is_valid) { i = va_arg(varpars, unsigned short*); b = parseStrLen (i,b,va_arg(varpars, char**)); } else { (void)va_arg (varpars, int*); (void)va_arg (varpars, char**); } break; #ifdef GPRS case 'E': if (value_is_valid) {/*lint -e78 -e26 -e530*/ b = parseExpo( -1, b, va_arg(varpars, T_PS_ber*)); } else { (void)va_arg (varpars, T_PS_ber*); } break; #endif case 'C': if (value_is_valid) { b = parseByte( -1, b, va_arg(varpars, unsigned char*)); } else { (void)va_arg (varpars, unsigned char*); } break; #ifdef GPRS case 'I': /* Parse cid_list */ if( value_is_valid ) { j = va_arg(varpars, unsigned char*); b = parseCid_list( b, j, va_arg(varpars, unsigned char*) ); } break; #endif /* GPRS */ case 'P': /* Parse pointer to string */ if( value_is_valid ) { b = parsePointerToString( (char)-1, b, va_arg(varpars, char**) ); } break; case '*': /* Parse '*' */ if( value_is_valid ) { if( *b NEQ '*' ) { return 0; } b++; } break; case '#': /* Parse '#' */ if( value_is_valid ) { if( *b NEQ '#' ) { return 0; } b++; } break; } if (!b) { va_end (varpars); /* Reset variable arguments. */ return 0; } if (*f AND *b EQ ',' AND value_is_valid) { b++; } else if (*b AND *b NEQ ';' AND *b NEQ ',' AND value_is_valid) /* if comma or semicolon is missing */ { TRACE_EVENT ("missing separator detected, aborting parse!"); va_end (varpars); return 0; } } if (*b AND *b NEQ ';') { va_end (varpars); /* Reset variable arguments. */ return 0; } va_end (varpars); /* Reset variable arguments. */ /*lint +e516 +e10*/ return b; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : ACI_PRS | | STATE : code ROUTINE : parse | +--------------------------------------------------------------------+ PURPOSE : get last parsed index (to determinate which component was malicious) */ GLOBAL UBYTE get_parse_index () { return parse_index; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : ACI_PRS | | STATE : code ROUTINE : parseByte(U8) | +--------------------------------------------------------------------+ PURPOSE : parse U8 value */ GLOBAL char *parseByte (int digits, char *b, U8 *i) { int found = 0; *i = 0; while (digits-- AND *b >= '0' AND *b <= '9') { found++; *i *= 10; *i += *b - '0'; b++; } return ((found) ? b : 0); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : ACI_PRS | | STATE : code ROUTINE : parseTimeStamp | +--------------------------------------------------------------------+ PURPOSE : Parse time stamp format in "yy/MM/dd,hh:mm:ss±zz" */ GLOBAL UBYTE parseTimeStamp( char *p_in,U8 *years,U8 *months,U8 *days, U8 *hrs, U8 *mins,U8 *secs, char *sign, U8 *time_zone ) { if( p_in[2] NEQ '/' OR p_in[5] NEQ '/' OR p_in[8] NEQ ',' OR p_in[11] NEQ ':' OR p_in[14] NEQ ':' ) { return NO_TIME_STAMP_FIELD; } if(!parseByte (2, &p_in[0], years)) { return NO_TIME_STAMP_FIELD; } if(!parseByte (2, &p_in[3], months)) { return NO_TIME_STAMP_FIELD; } if(!parseByte (2, &p_in[6], days)) { return NO_TIME_STAMP_FIELD; } if(!parseByte (2, &p_in[9], hrs)) { return NO_TIME_STAMP_FIELD; } if(!parseByte (2, &p_in[12], mins)) { return NO_TIME_STAMP_FIELD; } if(!parseByte (2, &p_in[15], secs)) { return NO_TIME_STAMP_FIELD; } *sign = p_in[17]; if(*sign NEQ '+' AND *sign NEQ '-' ) { return NO_TIME_STAMP_FIELD; } if(!parseByte (2, &p_in[18], time_zone)) { return NO_TIME_STAMP_FIELD; } return MAX_TIME_STAMP_FIELDS; } #endif /* ATI_PRS_C */