diff options
Diffstat (limited to 'src/gsmd/atcmd.c')
-rw-r--r-- | src/gsmd/atcmd.c | 159 |
1 files changed, 83 insertions, 76 deletions
diff --git a/src/gsmd/atcmd.c b/src/gsmd/atcmd.c index 1f2e04e..747000b 100644 --- a/src/gsmd/atcmd.c +++ b/src/gsmd/atcmd.c @@ -41,6 +41,7 @@ #include <gsmd/unsolicited.h> static void *__atcmd_ctx; +static int remove_timer(struct gsmd_atcmd * cmd); enum final_result_codes { GSMD_RESULT_OK = 0, @@ -200,12 +201,12 @@ static int parse_final_result(const char *res) return -1; } -static inline void atcmd_wake_pending_queue (struct gsmd *g) +void atcmd_wake_pending_queue (struct gsmd *g) { g->gfd_uart.when |= GSMD_FD_WRITE; } -static inline void atcmd_wait_pending_queue (struct gsmd *g) +void atcmd_wait_pending_queue (struct gsmd *g) { g->gfd_uart.when &= ~GSMD_FD_WRITE; } @@ -214,6 +215,8 @@ static inline void atcmd_wait_pending_queue (struct gsmd *g) static int atcmd_done(struct gsmd *g, struct gsmd_atcmd *cmd, const char *buf) { int rc = 0; + /* remove timer if get respond before timeout */ + remove_timer(cmd); if (!cmd->cb) { gsmd_log(GSMD_NOTICE, "command without cb!!!\n"); } else { @@ -359,6 +362,8 @@ static int ml_parse(const char *buf, int len, void *ctx) /* it might be a multiline response, so if there's a previous response, send out mlbuf and start afresh with an empty buffer */ if (g->mlbuf_len) { + /* remove timer if get respond before timeout */ + remove_timer(cmd); if (!cmd->cb) { gsmd_log(GSMD_NOTICE, "command without cb!!!\n"); } else { @@ -512,6 +517,8 @@ static int atcmd_select_cb(int fd, unsigned int what, void *data) write(fd, "\r", 1); if (!pos->buflen) { + /* success: create atcommand timeout timer */ + pos->timeout = pos->create_timer_func(g); /* success: remove from global list of * to-be-sent atcmds */ llist_del(&pos->list); @@ -536,9 +543,56 @@ static int atcmd_select_cb(int fd, unsigned int what, void *data) return 0; } +static void discard_timeout(struct gsmd_timer *tmr, void *data) +{ + struct gsmd *g=data; + struct gsmd_atcmd *cmd=NULL; + DEBUGP("discard time out!!\n"); + if (!llist_empty(&g->busy_atcmds)) { + cmd = llist_entry(g->busy_atcmds.next,struct gsmd_atcmd, list); + } + if (!cmd) { + DEBUGP("ERROR!! busy_atcmds is NULL\n"); + return; + } + if (cmd->timeout != tmr) { + DEBUGP("ERROR!! cmd->timeout != tmr\n"); + return; + } + + gsmd_timer_free(cmd->timeout); + cmd->timeout = NULL; + + if (cmd->cb) { + cmd->resp = "Timeout"; + cmd->cb(cmd, cmd->ctx, cmd->resp); + } + + // discard the timeout at command + llist_del(&cmd->list); + talloc_free(cmd); + + // pass the next pending at command + if (llist_empty(&g->busy_atcmds) && !llist_empty(&g->pending_atcmds)) { + atcmd_wake_pending_queue(g); + } +} + +static struct gsmd_timer * discard_timer(struct gsmd *g) +{ + + struct timeval tv; + tv.tv_sec = GSMD_ATCMD_TIMEOUT; + tv.tv_usec = 0; + + DEBUGP("Create discard timer\n"); + + return gsmd_timer_create(&tv, &discard_timeout, g); +} struct gsmd_atcmd *atcmd_fill(const char *cmd, int rlen, - atcmd_cb_t cb, void *ctx, u_int16_t id) + atcmd_cb_t cb, void *ctx, u_int16_t id, + create_timer_t ct) { int buflen = strlen(cmd); struct gsmd_atcmd *atcmd; @@ -559,95 +613,48 @@ struct gsmd_atcmd *atcmd_fill(const char *cmd, int rlen, atcmd->cur = atcmd->buf; atcmd->cb = cb; atcmd->resp = NULL; + atcmd->timeout = NULL; strncpy(atcmd->buf, cmd, buflen-1); - return atcmd; -} - -static int null_wakeup_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp) -{ - struct gsmd *g = ctx; - if (g->wakeup_timer) { - DEBUGP("modem is awake, remove timer!\n"); - gsmd_timer_unregister(g->wakeup_timer); - gsmd_timer_free(g->wakeup_timer); - g->wakeup_timer=NULL; - } else { - DEBUGP("ERROR!! The wake up response comes too late!!\n"); - } - return 0; -} + if (!ct) + atcmd->create_timer_func = discard_timer; + else + atcmd->create_timer_func = ct; -static void wakeup_timeout(struct gsmd_timer *tmr, void *data) -{ - struct gsmd *g=data; - struct gsmd_atcmd *cmd=NULL; - DEBUGP("Wakeup time out!!\n"); - if (g->wakeup_timer != tmr) { - DEBUGP("ERROR!! g->wakeup_timer != tmr\n"); - return; - } - g->wakeup_timer = NULL; - gsmd_timer_free(tmr); - if (!llist_empty(&g->busy_atcmds)) { - cmd = llist_entry(g->busy_atcmds.next,struct gsmd_atcmd, list); - } - if (!cmd) { - DEBUGP("ERROR!! busy_atcmds is NULL\n"); - return; - } - // It's a wakeup command - if ( cmd->buf[0]==' ') { - llist_del(&cmd->list); - talloc_free(cmd); - // discard the wakeup command, and pass the real command. - if (llist_empty(&g->busy_atcmds) && !llist_empty(&g->pending_atcmds)) { - atcmd_wake_pending_queue(g); - } - } else { - DEBUGP("ERROR!! Wakeup timeout and cmd->buf is not wakeup command!! %s\n",cmd->buf); - } + return atcmd; } -void wakeup_timer (struct gsmd *g) +static int remove_timer(struct gsmd_atcmd * cmd) { - struct timeval tv; - struct gsmd_timer *timer; - tv.tv_sec = GSMD_MODEM_WAKEUP_TIMEOUT; - tv.tv_usec = 0; - timer=gsmd_timer_create(&tv,&wakeup_timeout,g); - g->wakeup_timer=timer; - -} + if (cmd->timeout) { + DEBUGP("Get respond before timeout, remove timer!\n"); + gsmd_timer_unregister(cmd->timeout); + gsmd_timer_free(cmd->timeout); + cmd->timeout = NULL; + } else { + DEBUGP("ERROR!! The %s response comes too late!!\n", cmd->buf); + } -/// adding a null '\r' before real at command. -struct gsmd_atcmd * atcmd_wakeup_modem(struct gsmd *g) -{ - if (!g->wakeup_timer) { - DEBUGP("try to wake up\n"); - struct gsmd_atcmd * cmd= atcmd_fill(" \r",2,null_wakeup_cb,g,0); - wakeup_timer(g); - if (llist_empty(&g->pending_atcmds)) { - atcmd_wake_pending_queue(g); - } - llist_add_tail(&cmd->list, &g->pending_atcmds); - } + return 0; } - /* submit an atcmd in the global queue of pending atcmds */ int atcmd_submit(struct gsmd *g, struct gsmd_atcmd *cmd) { int empty; - atcmd_wakeup_modem(g); + + if (g->machinepl->ex_submit) { + DEBUGP("extra-submiting command\n"); + g->machinepl->ex_submit(g); + } DEBUGP("submitting command `%s'\n", cmd->buf); - empty = llist_empty(&g->pending_atcmds); llist_add_tail(&cmd->list, &g->pending_atcmds); - if (empty) { - atcmd_wake_pending_queue(g); - } + if (llist_empty(&g->busy_atcmds) && !llist_empty(&g->pending_atcmds)) { + atcmd_wake_pending_queue(g); + } + return 0; } @@ -701,7 +708,7 @@ int atcmd_init(struct gsmd *g, int sockfd) g->mlbuf_len = 0; g->mlunsolicited = 0; - g->wakeup_timer=NULL; + g->alive_responded = 0; g->llp.cur = g->llp.buf; g->llp.len = sizeof(g->llp.buf); |