Hi Martin, On 03/02/2011 03:59 AM, Xu, Martin wrote: > Looks like my smtp server has some issue currently. > So send the patch through attachment. > Sorry for inconvenient. > > diff --git a/plugins/huawei.c b/plugins/huawei.c > index 6f05677..5e2ee90 100644 > --- a/plugins/huawei.c > +++ b/plugins/huawei.c > @@ -78,6 +78,7 @@ struct huawei_data { > struct ofono_gprs *gprs; > struct ofono_gprs_context *gc; > gboolean voice; > + gboolean online; I don't think you really need this one, you can use the presence of gprs atom instead. > gboolean ndis; > guint sim_poll_timeout; > guint sim_poll_count; > @@ -97,6 +98,7 @@ static int huawei_probe(struct ofono_modem *modem) > if (data == NULL) > return -ENOMEM; > > + data->online = FALSE; > ofono_modem_set_data(modem, data); > > return 0; > @@ -111,6 +113,11 @@ static void huawei_remove(struct ofono_modem *modem) > ofono_modem_set_data(modem, NULL); > > if (data->modem) > + /* > + * huawei_disconnect should not be called when the chat > + * is closed initiatively > + */ > + g_at_chat_set_disconnect_function(data->modem, NULL, NULL); > g_at_chat_unref(data->modem); Are you missing some parentheses around the if statement now? Setting the disconnect function here seems fishy. We automatically set it to NULL when GAtIO is unref-ed. Seems to me g_at_chat_unref should be enough. > > g_at_chat_unref(data->pcui); > @@ -470,10 +477,7 @@ static void huawei_disconnect(gpointer user_data) > struct ofono_modem *modem = user_data; > struct huawei_data *data = ofono_modem_get_data(modem); > > - DBG(""); > - > - if (data->gc) > - ofono_gprs_context_remove(data->gc); > + DBG("data->online %d", data->online); > > g_at_chat_unref(data->modem); > data->modem = NULL; > @@ -485,6 +489,13 @@ static void huawei_disconnect(gpointer user_data) > g_at_chat_set_disconnect_function(data->modem, > huawei_disconnect, modem); > > + /* reopen GPRS context channel only at online state */ > + if (data->online == FALSE) > + return; > + > + if (data->gc) > + ofono_gprs_context_remove(data->gc); > + > if (data->sim_state == HUAWEI_SIM_STATE_VALID || > data->sim_state == HUAWEI_SIM_STATE_INVALID_CS) { > ofono_info("Reopened GPRS context channel"); > @@ -515,6 +526,11 @@ static int huawei_enable(struct ofono_modem *modem) > > data->pcui = open_device(modem, "Pcui", "PCUI: "); > if (data->pcui == NULL) { > + /* > + * huawei_disconnect should not be called when the chat > + * is closed initiatively > + */ > + g_at_chat_set_disconnect_function(data->modem, NULL, NULL); > g_at_chat_unref(data->modem); > data->modem = NULL; > return -EIO; > @@ -564,6 +580,11 @@ static int huawei_disable(struct ofono_modem *modem) > if (data->modem) { > g_at_chat_cancel_all(data->modem); > g_at_chat_unregister_all(data->modem); > + /* > + * huawei_disconnect should not be called when the chat > + * is closed initiatively > + */ > + g_at_chat_set_disconnect_function(data->modem, NULL, NULL); > g_at_chat_unref(data->modem); > data->modem = NULL; > } > @@ -579,15 +600,27 @@ static int huawei_disable(struct ofono_modem *modem) > return -EINPROGRESS; > } > > +struct huawei_cb_data { > + struct cb_data *cbd; > + ofono_bool_t online; > + struct ofono_modem *modem; > +}; > + > static void set_online_cb(gboolean ok, GAtResult *result, gpointer user_data) > { > - struct cb_data *cbd = user_data; > - ofono_modem_online_cb_t cb = cbd->cb; > + struct huawei_cb_data *online_cbd = user_data; > + ofono_modem_online_cb_t cb = online_cbd->cbd->cb; > + struct huawei_data *data = ofono_modem_get_data(online_cbd->modem); > > - if (ok) > - CALLBACK_WITH_SUCCESS(cb, cbd->data); > + if (ok) { > + data->online = online_cbd->online; > + > + CALLBACK_WITH_SUCCESS(cb, online_cbd->cbd->data); > + > + g_free(online_cbd); > + } > else > - CALLBACK_WITH_FAILURE(cb, cbd->data); > + CALLBACK_WITH_FAILURE(cb, online_cbd->cbd->data); > } All of this can be better accomplished by using two separate callbacks. One for online and one for offline. I suspect all you need to do is unref data->modem, set data->gc and data->gprs to NULL in the offline callback prior to calling back into the core. > > static void huawei_set_online(struct ofono_modem *modem, ofono_bool_t online, > @@ -595,21 +628,26 @@ static void huawei_set_online(struct ofono_modem *modem, ofono_bool_t online, > { > struct huawei_data *data = ofono_modem_get_data(modem); > GAtChat *chat = data->pcui; > - struct cb_data *cbd = cb_data_new(cb, user_data); > + struct huawei_cb_data *online_cbd; > char const *command = online ? "AT+CFUN=1" : "AT+CFUN=5"; > > DBG("modem %p %s", modem, online ? "online" : "offline"); > > - if (cbd == NULL) > + online_cbd = g_try_new0(struct huawei_cb_data, 1); > + online_cbd->cbd = cb_data_new(cb, user_data); > + if (online_cbd->cbd == NULL) > goto error; > + online_cbd->online = online; > + online_cbd->modem = modem; > > - if (g_at_chat_send(chat, command, NULL, set_online_cb, cbd, g_free)) > + if (g_at_chat_send(chat, command, NULL, set_online_cb, > + online_cbd, g_free)) > return; > > error: > - g_free(cbd); > + g_free(online_cbd); > > - CALLBACK_WITH_FAILURE(cb, cbd->data); > + CALLBACK_WITH_FAILURE(cb, user_data); > } > > static void huawei_pre_sim(struct ofono_modem *modem) > -- 1.6.1.3 Regards, -Denis