diff options
author | Martin Hundebøll <martin@geanix.com> | 2019-08-12 22:38:32 +0200 |
---|---|---|
committer | Denis Kenzior <denkenz@gmail.com> | 2019-08-13 02:09:22 -0500 |
commit | 61cca1809aca8ab486297712676885880f64b2b5 (patch) | |
tree | d7fd74074b8369fd38aed5287c46d056956b3042 /plugins | |
parent | e69a30f1df057407987931fc4f84c0f8e4687bd1 (diff) | |
download | ofono-61cca1809aca8ab486297712676885880f64b2b5.tar.gz |
quectel: replace g_at_chat_set_wakeup_command() with g_at_chat_retry()
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.
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/quectel.c | 64 |
1 files 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; } |