From d5876c34c4b6096479e2165ad21ef524206413a8 Mon Sep 17 00:00:00 2001 From: laforge Date: Tue, 31 Jul 2007 07:38:23 +0000 Subject: Add '2nd try' of the multiline parser: Every extended response causes a flush of the previous mlbuf and starts collecting new response lines. Also, final_cb is now really only reached for final responses and the code for case 'A' won't overwrite the command buffer with the response anymore. I throw in '\n' as a separator for multi-line responses, and the callback is called for each response this way. (Philipp Zabel) git-svn-id: http://svn.openmoko.org/trunk/src/target/gsm@2581 99fdad57-331a-0410-800a-d7fa5415bdb3 --- include/gsmd/gsmd.h | 5 +++- src/gsmd/atcmd.c | 70 ++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 54 insertions(+), 21 deletions(-) diff --git a/include/gsmd/gsmd.h b/include/gsmd/gsmd.h index b4dfa62..0ce753b 100644 --- a/include/gsmd/gsmd.h +++ b/include/gsmd/gsmd.h @@ -41,7 +41,10 @@ enum llparse_state { }; /* we can't take any _single_ response bigger than this: */ -#define LLPARSE_BUF_SIZE 256 +#define LLPARSE_BUF_SIZE 1024 + +/* we can't pare a mutiline response biger than this: */ +#define MLPARSE_BUF_SIZE 65535 struct llparser { enum llparse_state state; diff --git a/src/gsmd/atcmd.c b/src/gsmd/atcmd.c index 085b382..5cb9298 100644 --- a/src/gsmd/atcmd.c +++ b/src/gsmd/atcmd.c @@ -175,7 +175,9 @@ static int ml_parse(const char *buf, int len, void *ctx) { struct gsmd *g = ctx; struct gsmd_atcmd *cmd = NULL; + static char mlbuf[MLPARSE_BUF_SIZE]; int rc = 0, final = 0; + int mlbuf_len; DEBUGP("buf=`%s'(%d)\n", buf, len); @@ -268,12 +270,22 @@ static int ml_parse(const char *buf, int len, void *ctx) /* if we survive till here, it's a valid extd response * to an extended command and thus Case 'A' */ - - /* FIXME: solve multi-line responses ! */ - if (cmd->buflen < len) - len = cmd->buflen; - memcpy(cmd->buf, buf, len); + /* it might be a multiline response, so if there's a previous + response, send out mlbuf and start afresh with an empty buffer */ + if (mlbuf[0] != 0) { + if (!cmd->cb) { + gsmd_log(GSMD_NOTICE, "command without cb!!!\n"); + } else { + DEBUGP("Calling cmd->cb()\n"); + cmd->resp = mlbuf; + rc = cmd->cb(cmd, cmd->ctx, cmd->resp); + DEBUGP("Clearing mlbuf\n"); + mlbuf[0] = 0; + } + } + + /* the current buf will be appended to mlbuf below */ } } else { if (!strcmp(buf, "RING") || @@ -322,8 +334,25 @@ static int ml_parse(const char *buf, int len, void *ctx) /* we reach here, if we are at an information response that needs to be * passed on */ + if (mlbuf[0] == 0) { + DEBUGP("Filling mlbuf\n"); + strncat(mlbuf, buf, sizeof(mlbuf)-1); + } else { + DEBUGP("Appending buf to mlbuf\n"); + mlbuf_len = strlen(mlbuf); + if (mlbuf_len+1 < sizeof(mlbuf)) { + mlbuf[mlbuf_len] = '\n'; + mlbuf[mlbuf_len+1] = '\0'; + strncat(mlbuf, buf, sizeof(mlbuf)-mlbuf_len-2); + } else { + DEBUGP("response too big for mlbuf!!!\n"); + return -EFBIG; + } + } + return 0; + final_cb: - /* if we reach here, the final result code of a command has been reached */ + /* if reach here, the final result code of a command has been reached */ if (!cmd) return rc; @@ -334,24 +363,25 @@ final_cb: if (!cmd->cb) { gsmd_log(GSMD_NOTICE, "command without cb!!!\n"); } else { - if (!final || !cmd->resp) { - /* if we reach here, we didn't send any information responses yet */ - DEBUGP("Calling cmd->cb()\n"); + DEBUGP("Calling final cmd->cb()\n"); + /* send final result code if there is no information response in mlbuf */ + if (mlbuf[0] == 0) cmd->resp = buf; - rc = cmd->cb(cmd, cmd->ctx, buf); - } + else + cmd->resp = mlbuf; + rc = cmd->cb(cmd, cmd->ctx, cmd->resp); + DEBUGP("Clearing mlbuf\n"); + mlbuf[0] = 0; } - if (final) { - /* remove from list of currently executing cmds */ - llist_del(&cmd->list); - talloc_free(cmd); + /* remove from list of currently executing cmds */ + llist_del(&cmd->list); + talloc_free(cmd); - /* if we're finished with current commands, but still have pending - * commands: we want to WRITE again */ - if (llist_empty(&g->busy_atcmds) && !llist_empty(&g->pending_atcmds)) - g->gfd_uart.when |= GSMD_FD_WRITE; - } + /* if we're finished with current commands, but still have pending + * commands: we want to WRITE again */ + if (llist_empty(&g->busy_atcmds) && !llist_empty(&g->pending_atcmds)) + g->gfd_uart.when |= GSMD_FD_WRITE; return rc; } -- cgit v1.2.3