Fix: Retry the wakeup command until the modem OKs
authorDenis Kenzior <denkenz@gmail.com>
Thu, 26 Nov 2009 13:38:51 +0000 (07:38 -0600)
committerMarcel Holtmann <marcel@holtmann.org>
Thu, 26 Nov 2009 23:04:57 +0000 (23:04 +0000)
The calypso is weird where it doesn't actually wakeup on the first try,
we need to bang its head a few times until it responds

gatchat/gatchat.c

index ce04142..04995cc 100644 (file)
@@ -147,7 +147,8 @@ static struct at_command *at_command_create(const char *cmd,
                                                GAtNotifyFunc listing,
                                                GAtResultFunc func,
                                                gpointer user_data,
-                                               GDestroyNotify notify)
+                                               GDestroyNotify notify,
+                                               gboolean wakeup)
 {
        struct at_command *c;
        gsize len;
@@ -186,12 +187,16 @@ static struct at_command *at_command_create(const char *cmd,
        /* If we have embedded '\r' then this is a command expecting a prompt
         * from the modem.  Embed Ctrl-Z at the very end automatically
         */
-       if (strchr(cmd, '\r'))
-               c->cmd[len] = 26;
-       else
-               c->cmd[len] = '\r';
+       if (wakeup == FALSE) {
+               if (strchr(cmd, '\r'))
+                       c->cmd[len] = 26;
+               else
+                       c->cmd[len] = '\r';
+
+               len += 1;
+       }
 
-       c->cmd[len+1] = '\0';
+       c->cmd[len] = '\0';
 
        c->expect_pdu = expect_pdu;
        c->prefixes = prefixes;
@@ -802,23 +807,40 @@ static gboolean received_data(GIOChannel *channel, GIOCondition cond,
        return TRUE;
 }
 
+static void wakeup_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+       GAtChat *chat = user_data;
+
+       if (ok == FALSE)
+               return;
+
+       if (chat->debugf)
+               chat->debugf("Finally woke up the modem\n", chat->debug_data);
+
+       g_source_remove(chat->timeout_source);
+       chat->timeout_source = 0;
+}
+
 static gboolean wakeup_no_response(gpointer user)
 {
        GAtChat *chat = user;
        struct at_command *cmd = g_queue_peek_head(chat->command_queue);
 
-       chat->timeout_source = 0;
+       if (chat->debugf)
+               chat->debugf("Wakeup got no response\n", chat->debug_data);
 
-       /* Sometimes during startup the modem is still in the ready state
-        * and might acknowledge our 'wakeup' command.  In that case don't
-        * timeout the wrong command
-        */
-       if (cmd == NULL || cmd->id != 0)
+       g_at_chat_finish_command(chat, FALSE, NULL);
+       cmd = at_command_create(chat->wakeup, none_prefix, FALSE,
+                               NULL, wakeup_cb, chat, NULL, TRUE);
+
+       if (!cmd) {
+               chat->timeout_source = 0;
                return FALSE;
+       }
 
-       g_at_chat_finish_command(chat, FALSE, NULL);
+       g_queue_push_head(chat->command_queue, cmd);
 
-       return FALSE;
+       return TRUE;
 }
 
 static gboolean can_write_data(GIOChannel *channel, GIOCondition cond,
@@ -869,7 +891,7 @@ static gboolean can_write_data(GIOChannel *channel, GIOCondition cond,
 
        if (chat->cmd_bytes_written == 0 && wakeup_first == TRUE) {
                cmd = at_command_create(chat->wakeup, none_prefix, FALSE,
-                                       NULL, NULL, NULL, NULL);
+                                       NULL, wakeup_cb, chat, NULL, TRUE);
 
                if (!cmd)
                        return FALSE;
@@ -1116,7 +1138,7 @@ static guint send_common(GAtChat *chat, const char *cmd,
                return 0;
 
        c = at_command_create(cmd, prefix_list, expect_pdu, listing, func,
-                               user_data, notify);
+                               user_data, notify, FALSE);
 
        if (!c)
                return 0;