Hi Christophe, On 02/15/2017 10:38 AM, Christophe Ronco wrote: > Some modems do not support AT+CGDATA="PPP",X to enter data state. > Use AT+CGDATA=? to detect these modems and for them use ATD*99***X# > to enter data state. > --- > drivers/atmodem/gprs-context.c | 44 +++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 43 insertions(+), 1 deletion(-) > > diff --git a/drivers/atmodem/gprs-context.c b/drivers/atmodem/gprs-context.c > index f6e6c2ef..bfe0d4b5 100644 > --- a/drivers/atmodem/gprs-context.c > +++ b/drivers/atmodem/gprs-context.c > @@ -47,6 +47,7 @@ > > #define STATIC_IP_NETMASK "255.255.255.255" > > +static const char *cgdata_prefix[] = { "+CGDATA:", NULL }; > static const char *none_prefix[] = { NULL }; > > enum state { > @@ -67,6 +68,7 @@ struct gprs_context_data { > ofono_gprs_context_cb_t cb; > void *cb_data; /* Callback data */ > unsigned int vendor; > + gboolean use_atd99; > }; > > static void ppp_debug(const char *str, void *data) > @@ -210,7 +212,7 @@ static void at_cgdcont_cb(gboolean ok, GAtResult *result, gpointer user_data) > return; > } > > - if (gcd->vendor == OFONO_VENDOR_SIMCOM_SIM900) > + if (gcd->use_atd99) > sprintf(buf, "ATD*99***%u#", gcd->active_context); > else > sprintf(buf, "AT+CGDATA=\"PPP\",%u", gcd->active_context); > @@ -378,6 +380,43 @@ static void cgev_notify(GAtResult *result, gpointer user_data) > g_at_ppp_shutdown(gcd->ppp); > } > > +static void at_cgdata_test_cb(gboolean ok, GAtResult *result, > + gpointer user_data) > +{ > + struct ofono_gprs_context *gc = user_data; > + struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); > + GAtResultIter iter; > + const char *data_type; > + gboolean found = FALSE; > + > + gcd->use_atd99 = TRUE; > + > + if (!ok) { > + DBG("not ok"); > + goto error; > + } > + > + g_at_result_iter_init(&iter, result); > + if (!g_at_result_iter_next(&iter, "+CGDATA:")) { > + DBG("no +CGDATA line"); > + goto error; > + } > + > + if (!g_at_result_iter_open_list(&iter)) { > + DBG("no list found"); > + goto error; > + } > + > + while (!found && g_at_result_iter_next_string(&iter, &data_type)) { > + if (g_str_equal(data_type, "PPP")) { > + found = TRUE; > + gcd->use_atd99 = FALSE; > + } > + } > +error: > + DBG("use_atd99:%d", gcd->use_atd99); > +} > + > static int at_gprs_context_probe(struct ofono_gprs_context *gc, > unsigned int vendor, void *data) > { > @@ -405,6 +444,9 @@ static int at_gprs_context_probe(struct ofono_gprs_context *gc, > if (chat == NULL) > return 0; > > + g_at_chat_send(chat, "AT+CGDATA=?", cgdata_prefix, at_cgdata_test_cb, > + gc, NULL); > + Looks fine to me. My only comment would be to skip the CGDATA query if the vendor quirk explicitly tells us to use ATD*99. So e.g. switch (vendor) { case OFONO_VENDOR_SIMCOM_SIM900: use_atd99 = FALSE; break; default: g_at_chat_send(chat, "AT+CGDATA=?", ...); } > g_at_chat_register(chat, "+CGEV:", cgev_notify, FALSE, gc, NULL); > > return 0; > Regards, -Denis