static void ril_gprs_context_call_list_changed(struct ril_msg *message, gpointer user_data) { struct ofono_gprs_context *gc = user_data; struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); struct data_call *call = NULL; struct unsol_data_call_list *unsol; gboolean active_cid_found = FALSE; gboolean disconnect = FALSE; GSList *iterator = NULL; struct ofono_error error; unsol = g_ril_unsol_parse_data_call_list(gcd->ril, message, &error); if (error.type != OFONO_ERROR_TYPE_NO_ERROR) goto error; DBG("number of call in call_list_changed is: %d", unsol->num); for (iterator = unsol->call_list; iterator; iterator = iterator->next) { call = (struct data_call *) iterator->data; if (call->cid == gcd->active_rild_cid) { active_cid_found = TRUE; if (call->active == 0) { disconnect = TRUE; ofono_gprs_context_deactivated(gc, gcd->active_ctx_cid); } break; } } if (disconnect || active_cid_found == FALSE) { ofono_error("Clearing active context"); set_context_disconnected(gcd); } error: g_ril_unsol_free_data_call_list(unsol); }
static void get_active_data_calls_cb(struct ril_msg *message, gpointer user_data) { struct ofono_gprs *gprs = user_data; struct ril_gprs_data *gd = ofono_gprs_get_data(gprs); struct ril_data_call_list *call_list = NULL; GSList *iterator; struct ril_data_call *call; if (message->error != RIL_E_SUCCESS) { ofono_error("%s: RIL error %s", __func__, ril_error_to_string(message->error)); goto end; } /* reply can be NULL when there are no existing data calls */ call_list = g_ril_unsol_parse_data_call_list(gd->ril, message); if (call_list == NULL) goto end; /* * We disconnect from previous calls here, which might be needed * because of a previous ofono abort, as some rild implementations do * not disconnect the calls even after the ril socket is closed. */ for (iterator = call_list->calls; iterator; iterator = iterator->next) { call = iterator->data; DBG("Standing data call with cid %d", call->cid); if (drop_data_call(gprs, call->cid) == 0) ++(gd->pending_deact_req); } g_ril_unsol_free_data_call_list(call_list); end: if (gd->pending_deact_req == 0) ril_gprs_registration_status(gprs, NULL, NULL); }
/* * This function handles RIL_UNSOL_DATA_CALL_LIST_CHANGED messages, * as well as RIL_REQUEST_DATA_CALL_LIST/SETUP_DATA_CALL replies, as * all have the same payload. */ struct ril_data_call_list *g_ril_unsol_parse_data_call_list(GRil *gril, const struct ril_msg *message) { struct ril_data_call *call; struct parcel rilp; struct ril_data_call_list *reply = NULL; unsigned int active, cid, i, num_calls, retry, status; char *type = NULL, *ifname = NULL, *raw_addrs = NULL; char *raw_dns = NULL, *raw_gws = NULL; DBG(""); /* Can happen for RIL_REQUEST_DATA_CALL_LIST replies */ if (message->buf_len < MIN_DATA_CALL_LIST_SIZE) { if (message->req == RIL_REQUEST_SETUP_DATA_CALL) { ofono_error("%s: message too small: %d", __func__, (int) message->buf_len); goto error; } else { g_ril_append_print_buf(gril, "{"); goto done; } } reply = g_try_new0(struct ril_data_call_list, 1); if (reply == NULL) { ofono_error("%s: out of memory", __func__); goto error; } g_ril_init_parcel(message, &rilp); /* * ril.h documents the reply to a RIL_REQUEST_DATA_CALL_LIST * as being an array of RIL_Data_Call_Response_v6 structs, * however in reality, the response also includes a version * to start. */ reply->version = parcel_r_int32(&rilp); num_calls = parcel_r_int32(&rilp); g_ril_append_print_buf(gril, "{version=%d,num=%d", reply->version, num_calls); for (i = 0; i < num_calls; i++) { status = parcel_r_int32(&rilp); retry = parcel_r_int32(&rilp); /* ignore */ cid = parcel_r_int32(&rilp); active = parcel_r_int32(&rilp); type = parcel_r_string(&rilp); ifname = parcel_r_string(&rilp); raw_addrs = parcel_r_string(&rilp); raw_dns = parcel_r_string(&rilp); raw_gws = parcel_r_string(&rilp); /* malformed check */ if (rilp.malformed) { ofono_error("%s: malformed parcel received", __func__); goto error; } g_ril_append_print_buf(gril, "%s [status=%d,retry=%d,cid=%d," "active=%d,type=%s,ifname=%s," "address=%s,dns=%s,gateways=%s]", print_buf, status, retry, cid, active, type, ifname, raw_addrs, raw_dns, raw_gws); call = g_try_new0(struct ril_data_call, 1); if (call == NULL) { ofono_error("%s: out of memory", __func__); goto error; } call->status = status; call->cid = cid; call->active = active; if (message->req == RIL_REQUEST_SETUP_DATA_CALL && status == PDP_FAIL_NONE && handle_settings(call, type, ifname, raw_addrs, raw_dns, raw_gws) == FALSE) goto error; g_free(type); g_free(ifname); g_free(raw_addrs); g_free(raw_dns); g_free(raw_gws); reply->calls = g_slist_insert_sorted(reply->calls, call, data_call_compare); } done: g_ril_append_print_buf(gril, "%s}", print_buf); if (message->unsolicited) g_ril_print_unsol(gril, message); else g_ril_print_response(gril, message); return reply; error: g_free(type); g_free(ifname); g_free(raw_addrs); g_free(raw_dns); g_free(raw_gws); g_ril_unsol_free_data_call_list(reply); return NULL; }
static void ril_gprs_context_call_list_changed(struct ril_msg *message, gpointer user_data) { struct ofono_gprs_context *gc = user_data; struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); struct data_call *call = NULL; struct unsol_data_call_list *unsol; gboolean disconnect = FALSE; GSList *iterator = NULL; struct ofono_error error; unsol = g_ril_unsol_parse_data_call_list(gcd->ril, message, &error); if (error.type != OFONO_ERROR_TYPE_NO_ERROR) goto error; DBG("number of call in call_list_changed is: %d", unsol->num); for (iterator = unsol->call_list; iterator; iterator = iterator->next) { call = (struct data_call *) iterator->data; if (call->status != 0) ofono_info("data call status:%d", call->status); if (call->active == DATA_CALL_INACTIVE) { disconnect = TRUE; ofono_gprs_context_deactivated(gc, gcd->active_ctx_cid); break; } if (call->active == DATA_CALL_ACTIVE) { char **split_ip_addr = NULL; const char **dns_addresses; if (call->ifname) { ofono_gprs_context_set_interface(gc, call->ifname); } if (call->addresses) { ofono_gprs_context_set_ipv4_netmask(gc, ril_util_get_netmask(call->addresses)); split_ip_addr = g_strsplit(call->addresses, "/", 2); ofono_gprs_context_set_ipv4_address(gc, split_ip_addr[0], TRUE); } if (call->gateways) { ofono_gprs_context_set_ipv4_gateway(gc, call->gateways); } if (call->dnses) DBG("dnses:%s", call->dnses); dns_addresses = (const char **)(call->dnses ? g_strsplit((const gchar*)call->dnses, " ", 3) : NULL); ofono_gprs_context_set_ipv4_dns_servers(gc, dns_addresses); break; } } if (disconnect) { ofono_error("Clearing active context"); set_context_disconnected(gcd); } error: g_ril_unsol_free_data_call_list(unsol); }