From 3026b93e266558671bd361b6c07546f8174974bc Mon Sep 17 00:00:00 2001 From: laforge Date: Sat, 10 Mar 2007 22:05:17 +0000 Subject: * include stdio from talloc.h * add new generic extended-response parser * add operator cache, using ext-resp-parser * add proper detection of supported %CPI modes and select highest available one * add %CTZV to vendor_ti init string git-svn-id: http://svn.openmoko.org/trunk/src/target/gsm@1316 99fdad57-331a-0410-800a-d7fa5415bdb3 --- src/gsmd/ext_response.c | 213 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 src/gsmd/ext_response.c (limited to 'src/gsmd/ext_response.c') diff --git a/src/gsmd/ext_response.c b/src/gsmd/ext_response.c new file mode 100644 index 0000000..5b31c8d --- /dev/null +++ b/src/gsmd/ext_response.c @@ -0,0 +1,213 @@ +/* gsmd extended response parser + * + * (C) 2007 by OpenMoko, Inc. + * Written by Harald Welte + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "gsmd.h" + +#include +#include +#include +#include + +int extrsp_supports(const struct gsm_extrsp *er, int index, int value) +{ + int i; + + if (index >= er->num_tokens) + return -EINVAL; + if (er->tokens[index].type != GSMD_ECMD_RTT_RANGE) + return -EINVAL; + + for (i = 0; i < er->tokens[index].u.range.num_items; i++) { + struct gsm_extrsp_range_item *ri = + &er->tokens[index].u.range.item[i]; + if (value >= ri->min && value <= ri->max) + return 1; + } + + return 0; +} + +enum parser_state { + IDLE, + TOKEN_STRING, + TOKEN_STRING_LASTQUOTE, + TOKEN_NUMERIC, + TOKEN_RANGE, +}; + +/* parse a comma-separated list, possibly containing quote values */ +struct gsm_extrsp *extrsp_parse(const void *ctx, const char *input) +{ + const char *cur = input; + struct gsm_extrsp *er; + int cur_tok = 0; + enum parser_state state = IDLE; + char buf[512]; + char *cur_buf = buf; + struct gsm_extrsp_tok *cur_token; + + if (!input || strlen(input) == 0) + return NULL; + + er = talloc(ctx, struct gsm_extrsp); + if (!er) + return NULL; + memset(er, 0, sizeof(*er)); + + while (*cur) { + cur_token = &er->tokens[er->num_tokens]; + + switch (state) { + case IDLE: + memset(buf, 0, sizeof(buf)); + cur_buf = buf; + + if (isblank(*cur)) + break; + else if (*cur == '"') { + cur_token->type = GSMD_ECMD_RTT_STRING; + state = TOKEN_STRING; + } else if (*cur == '(') { + cur_token->type = GSMD_ECMD_RTT_RANGE; + state = TOKEN_RANGE; + } else if (isdigit(*cur)) { + cur_token->type = GSMD_ECMD_RTT_NUMERIC; + *cur_buf = *cur; + cur_buf++; + state = TOKEN_NUMERIC; + } else if (*cur == ',') { + cur_token->type = GSMD_ECMD_RTT_EMPTY; + er->num_tokens++; + state = IDLE; + } + break; + case TOKEN_NUMERIC: + if (*cur == ',') { + /* end of number */ + cur_token->u.numeric = atoi(buf); + er->num_tokens++; + state = IDLE; + } else if (isdigit(*cur)) { + *cur_buf = *cur; + cur_buf++; + } else { + /* ERORR */ + } + break; + case TOKEN_STRING: + if (*cur == '"') { + int len = strlen(buf); + if (len > sizeof(cur_token->u.string)-1) + len = sizeof(cur_token->u.string)-1; + + /* end of string token */ + strncpy(cur_token->u.string, buf, len); + er->num_tokens++; + state = TOKEN_STRING_LASTQUOTE; + } else { + *cur_buf = *cur; + cur_buf++; + } + break; + case TOKEN_STRING_LASTQUOTE: + if (*cur == ',') + state = IDLE; + else { + /* ERROR */ + } + break; + case TOKEN_RANGE: + if (isdigit(*cur)) { + *cur_buf = *cur; + cur_buf++; + } else if (*cur == '-') { + /* previous number has completed */ + cur_token->u.range.item[cur_token->u.range.num_items].min = atoi(buf); + memset(buf, 0, sizeof(buf)); + cur_buf = buf; + } else if (*cur == ',') { + /* previous number has completed */ + cur_token->u.range.item[cur_token->u.range.num_items].max = atoi(buf); + cur_token->u.range.num_items++; + } else if (*cur == ')') { + /* previous number has completed */ + cur_token->u.range.item[cur_token->u.range.num_items].max = atoi(buf); + cur_token->u.range.num_items++; + state = TOKEN_STRING_LASTQUOTE; + er->num_tokens++; + } else { + /* ERROR */ + } + break; + } + cur++; + } + + //extrsp_dump(er); + return er; +} + +static const char *er_tok_names[] = { + [GSMD_ECMD_RTT_EMPTY] = "EMPTY", + [GSMD_ECMD_RTT_NUMERIC] = "NUMERIC", + [GSMD_ECMD_RTT_STRING] = "STRING", + [GSMD_ECMD_RTT_RANGE] = "RANGE", +}; + +void extrsp_dump(const struct gsm_extrsp *er) +{ + int i; + + DEBUGP("entering(er=%p, num_tokens=%u)\n", er, er->num_tokens); + for (i = 0; i < er->num_tokens; i++) { + const struct gsm_extrsp_tok *tok = &er->tokens[i]; + DEBUGP("Token %u: %s: ", i, er_tok_names[tok->type]); + switch (tok->type) { + case GSMD_ECMD_RTT_EMPTY: + DEBUGP("\n"); + break; + case GSMD_ECMD_RTT_NUMERIC: + DEBUGP("%d\n", tok->u.numeric); + break; + case GSMD_ECMD_RTT_STRING: + DEBUGP("%s\n", tok->u.string); + break; + case GSMD_ECMD_RTT_RANGE: { + int j; + for (j = 0; j < tok->u.range.num_items; j++) + DEBUGP("%d-%d, ", tok->u.range.item[j].min, + tok->u.range.item[j].max); + } + + break; + } + } + +} -- cgit v1.2.3