From 57b4aa367881e2bd11e41e96f68e9e6fe1b8a403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Wed, 10 Jul 2019 23:51:48 +0200 Subject: [PATCH] quectel: initialize call, phonebook and sms when ready The Quectel M95 modem issues a "Call ready" notification when call and phonebook are ready, so set up a listener for that. The only way to know when sms is ready is to issue QINITSTAT queries. Since sms is always ready after call and phonebook, the queries are initiated after creating call/phonebook. --- plugins/quectel.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/plugins/quectel.c b/plugins/quectel.c index 8cc1ecd4..11b864bc 100644 --- a/plugins/quectel.c +++ b/plugins/quectel.c @@ -42,6 +42,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -51,6 +54,7 @@ static const char *cfun_prefix[] = { "+CFUN:", NULL }; static const char *cpin_prefix[] = { "+CPIN:", NULL }; +static const char *qinistat_prefix[] = { "+QINISTAT:", NULL }; static const char *cgmm_prefix[] = { "UC15", "Quectel_M95", NULL }; static const char *none_prefix[] = { NULL }; @@ -69,8 +73,10 @@ struct quectel_data { GAtChat *modem; GAtChat *aux; guint cpin_ready; + guint call_ready; bool have_sim; enum ofono_vendor vendor; + struct l_timeout *sms_ready_timer; /* used by quectel uart driver */ GAtChat *uart; @@ -334,6 +340,66 @@ static void cgmm_cb(int ok, GAtResult *result, void *user_data) NULL); } +static void qinistat_cb(gboolean ok, GAtResult *result, gpointer user_data) +{ + struct ofono_modem *modem = user_data; + struct quectel_data *data = ofono_modem_get_data(modem); + GAtResultIter iter; + int status; + + DBG("%p", modem); + + g_at_result_iter_init(&iter, result); + + if (!g_at_result_iter_next(&iter, "+QINISTAT:")) + return; + + if (!g_at_result_iter_next_number(&iter, &status)) + return; + + DBG("qinistat: %d", status); + + if (status != 3) { + l_timeout_modify_ms(data->sms_ready_timer, 500); + return; + } + + ofono_sms_create(modem, data->vendor, "atmodem", data->aux); + l_timeout_remove(data->sms_ready_timer); + data->sms_ready_timer = NULL; +} + +static void sms_ready_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); + + g_at_chat_send(data->aux, "AT+QINISTAT", qinistat_prefix, qinistat_cb, + modem, NULL); +} + +static void call_ready_notify(GAtResult *result, void *user_data) +{ + struct ofono_modem *modem = user_data; + struct quectel_data *data = ofono_modem_get_data(modem); + + DBG("%p", modem); + + g_at_chat_unregister(data->aux, data->call_ready); + data->call_ready = 0; + data->sms_ready_timer = l_timeout_create_ms(500, sms_ready_cb, modem, + NULL); + if (!data->sms_ready_timer) { + close_serial(modem); + return; + } + + ofono_phonebook_create(modem, 0, "atmodem", data->aux); + ofono_voicecall_create(modem, 0, "atmodem", data->aux); +} + static int open_ttys(struct ofono_modem *modem) { struct quectel_data *data = ofono_modem_get_data(modem); @@ -353,6 +419,14 @@ static int open_ttys(struct ofono_modem *modem) return -EIO; } + data->call_ready = g_at_chat_register(data->aux, "Call Ready", + call_ready_notify, false, + modem, NULL); + if (!data->call_ready) { + close_serial(modem); + return -ENOTTY; + } + g_at_chat_set_slave(data->modem, data->aux); g_at_chat_send(data->modem, "ATE0; &C0; +CMEE=1", none_prefix, NULL,