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,