summaryrefslogtreecommitdiff
path: root/src/gsmd/atcmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gsmd/atcmd.c')
-rw-r--r--src/gsmd/atcmd.c159
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);
personal git repositories of Harald Welte. Your mileage may vary