If the modem isn't powered on, the use of g_at_chat_set_wakeup_command()
makes ofono send out AT strings in an endless loop. Avoid this by using
g_at_chat_retry() in a timer instead.
---
 plugins/quectel.c | 64 +++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 53 insertions(+), 11 deletions(-)

diff --git a/plugins/quectel.c b/plugins/quectel.c
index bddf6a17..eef66ced 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -99,6 +99,9 @@ struct quectel_data {
        int mux_ready_count;
        int initial_ldisc;
        struct l_gpio_writer *gpio;
+       struct l_timeout *init_timeout;
+       size_t init_count;
+       guint init_cmd;
 };
 
 struct dbus_hw {
@@ -186,6 +189,7 @@ static void quectel_remove(struct ofono_modem *modem)
                g_at_chat_unregister(data->aux, data->cpin_ready);
 
        ofono_modem_set_data(modem, NULL);
+       l_timeout_remove(data->init_timeout);
        l_gpio_writer_free(data->gpio);
        g_at_chat_unref(data->aux);
        g_at_chat_unref(data->modem);
@@ -867,6 +871,47 @@ static void ate_cb(int ok, GAtResult *result, void 
*user_data)
                        cmux_cb, modem, NULL);
 }
 
+static void init_cmd_cb(gboolean ok, GAtResult *result, void *user_data)
+{
+       struct ofono_modem *modem = user_data;
+       struct quectel_data *data = ofono_modem_get_data(modem);
+       const char *rts_cts;
+
+       DBG("%p", modem);
+
+       if (!ok)
+               return;
+
+       rts_cts = ofono_modem_get_string(modem, "RtsCts");
+
+       if (strcmp(rts_cts, "on") == 0)
+               g_at_chat_send(data->uart, "AT+IFC=2,2; E0", none_prefix,
+                               ate_cb, modem, NULL);
+       else
+               g_at_chat_send(data->uart, "ATE0", none_prefix, ate_cb, modem,
+                               NULL);
+
+       l_timeout_remove(data->init_timeout);
+       data->init_timeout = NULL;
+}
+
+static void init_timeout_cb(struct l_timeout *timeout, void *user_data)
+{
+       struct ofono_modem *modem = user_data;
+       struct quectel_data *data = ofono_modem_get_data(modem);
+
+       DBG("%p", modem);
+
+       if (data->init_count++ >= 20) {
+               ofono_error("failed to init modem after 20 attempts");
+               close_serial(modem);
+               return;
+       }
+
+       g_at_chat_retry(data->uart, data->init_cmd);
+       l_timeout_modify_ms(timeout, 500);
+}
+
 static int open_serial(struct ofono_modem *modem)
 {
        struct quectel_data *data = ofono_modem_get_data(modem);
@@ -910,18 +955,15 @@ static int open_serial(struct ofono_modem *modem)
         *     a few 'AT' bytes to detect the host UART bitrate, but the RDY is
         *     lost.
         *
-        * the wakeup command feature is (mis)used to support all three
-        * scenarious by sending AT commands until the modem responds with OK,
-        * at which point the modem is ready.
+        * Handle all three cases by issuing a plain AT command. The modem
+        * answers with OK when it is ready. Create a timer to re-issue
+        * the AT command at regular intervals until the modem answers.
         */
-       g_at_chat_set_wakeup_command(data->uart, "AT\r", 500, 10000);
-
-       if (strcmp(rts_cts, "on") == 0)
-               g_at_chat_send(data->uart, "AT+IFC=2,2; E0", none_prefix,
-                               ate_cb, modem, NULL);
-       else
-               g_at_chat_send(data->uart, "ATE0", none_prefix, ate_cb, modem,
-                               NULL);
+       data->init_count = 0;
+       data->init_cmd = g_at_chat_send(data->uart, "AT", none_prefix,
+                                       init_cmd_cb, modem, NULL);
+       data->init_timeout = l_timeout_create_ms(500, init_timeout_cb, modem,
+                                                       NULL);
 
        return -EINPROGRESS;
 }
-- 
2.22.0

_______________________________________________
ofono mailing list
ofono@ofono.org
https://lists.ofono.org/mailman/listinfo/ofono

Reply via email to