static void ril_gprs_set_pref_network(struct ofono_gprs *gprs) { struct gprs_data *gd = ofono_gprs_get_data(gprs); struct parcel rilp; DBG(""); /* * TODO (OEM): * * The preferred network type may need to be set * on a device-specific basis. For now, we use * GSM_WCDMA which prefers WCDMA ( ie. HS* ) over * the base GSM. */ parcel_init(&rilp); parcel_w_int32(&rilp, PREF_NET_TYPE_GSM_WCDMA); if (g_ril_send(gd->ril, RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, rilp.data, rilp.size, ril_gprs_set_pref_network_cb, NULL, NULL) <= 0) { ofono_error("Send RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE failed."); } parcel_free(&rilp); }
static void ril_gprs_set_attached(struct ofono_gprs *gprs, int attached, ofono_gprs_cb_t cb, void *data) { struct cb_data *cbd = cb_data_new(cb, data); struct gprs_data *gd = ofono_gprs_get_data(gprs); struct ofono_error error; DBG("attached: %d", attached); decode_ril_error(&error, "OK"); /* * As RIL offers no actual control over the GPRS 'attached' * state, we save the desired state, and use it to override * the actual modem's state in the 'attached_status' function. * This is similar to the way the core ofono gprs code handles * data roaming ( see src/gprs.c gprs_netreg_update(). * * The core gprs code calls driver->set_attached() when a netreg * notificaiton is received and any configured roaming conditions * are met. */ gd->ofono_attached = attached; cb(&error, cbd->data); g_free(cbd); }
static void at_gprs_remove(struct ofono_gprs *gprs) { struct gprs_data *gd = ofono_gprs_get_data(gprs); ofono_gprs_set_data(gprs, NULL); g_free(gd); }
static void ril_gprs_registration_status(struct ofono_gprs *gprs, ofono_gprs_status_cb_t cb, void *data) { struct gprs_data *gd = ofono_gprs_get_data(gprs); struct cb_data *cbd = cb_data_new(cb, data); int request = RIL_REQUEST_DATA_REGISTRATION_STATE; guint ret; DBG(""); if (gd == NULL || cbd == NULL) return; cbd->user = gprs; ret = g_ril_send(gd->ril, request, NULL, 0, ((gd->rild_status == -1) ? ril_data_probe_reg_cb : ril_data_reg_cb), cbd, g_free); g_ril_print_request_no_args(gd->ril, ret, request); if (ret <= 0) { ofono_error("Send RIL_REQUEST_DATA_RESTISTRATION_STATE fail."); g_free(cbd); if (cb) CALLBACK_WITH_FAILURE(cb, -1, data); } }
static void at_gprs_registration_status(struct ofono_gprs *gprs, ofono_gprs_status_cb_t cb, void *data) { struct gprs_data *gd = ofono_gprs_get_data(gprs); struct cb_data *cbd = cb_data_new(cb, data); if (!cbd) goto error; cbd->user = gd; switch (gd->vendor) { case OFONO_VENDOR_NOVATEL: /* * Send $CNTI=0 to find out the current tech, it will be * intercepted in nw_cnti_notify in network registration */ g_at_chat_send(gd->chat, "AT$CNTI=0", none_prefix, NULL, NULL, NULL); break; } if (g_at_chat_send(gd->chat, "AT+CGREG?", cgreg_prefix, at_cgreg_cb, cbd, g_free) > 0) return; error: if (cbd) g_free(cbd); CALLBACK_WITH_FAILURE(cb, -1, data); }
void ril_gprs_set_ia_apn(struct ofono_gprs *gprs, const char *apn, enum ofono_gprs_proto proto, const char *user, const char *passwd, const char *mccmnc, ofono_gprs_cb_t cb, void *data) { struct ril_gprs_data *gd = ofono_gprs_get_data(gprs); struct cb_data *cbd; struct parcel rilp; if (!ofono_modem_get_boolean(gd->modem, MODEM_PROP_LTE_CAPABLE)) { CALLBACK_WITH_SUCCESS(cb, data); return; } cbd = cb_data_new(cb, data, gprs); g_ril_request_set_initial_attach_apn(gd->ril, apn, proto, user, passwd, mccmnc, &rilp); if (g_ril_send(gd->ril, RIL_REQUEST_SET_INITIAL_ATTACH_APN, &rilp, set_ia_apn_cb, cbd, g_free) == 0) { ofono_error("%s: failure sending request", __func__); g_free(cbd); CALLBACK_WITH_FAILURE(cb, data); } }
static void cgev_notify(GAtResult *result, gpointer user_data) { struct ofono_gprs *gprs = user_data; struct gprs_data *gd = ofono_gprs_get_data(gprs); GAtResultIter iter; const char *event; g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+CGEV:")) return; if (!g_at_result_iter_next_unquoted_string(&iter, &event)) return; if (g_str_equal(event, "NW DETACH") || g_str_equal(event, "ME DETACH")) { if (gd->vendor == OFONO_VENDOR_TELIT && gd->telit_try_reattach) return; gd->attached = FALSE; ofono_gprs_detached_notify(gprs); return; } else if (g_str_has_prefix(event, "ME PDN ACT")) { sscanf(event, "%*s %*s %*s %u", &gd->last_auto_context_id); g_at_chat_send(gd->chat, "AT+CGDCONT?", cgdcont_prefix, at_cgdcont_read_cb, gprs, NULL); } }
static void ril_gprs_set_attached(struct ofono_gprs *gprs, int attached, ofono_gprs_cb_t cb, void *data) { struct cb_data *cbd = cb_data_new(cb, data, NULL); struct ril_gprs_data *gd = ofono_gprs_get_data(gprs); DBG("attached: %d", attached); /* * As RIL offers no actual control over the GPRS 'attached' * state, we save the desired state, and use it to override * the actual modem's state in the 'attached_status' function. * This is similar to the way the core ofono gprs code handles * data roaming ( see src/gprs.c gprs_netreg_update(). * * The core gprs code calls driver->set_attached() when a netreg * notificaiton is received and any configured roaming conditions * are met. */ gd->ofono_attached = attached; /* * Call from idle loop, so core can set driver_attached before * the callback is invoked. */ g_idle_add(ril_gprs_set_attached_cb, cbd); }
static void mtk_gprs_set_attached(struct ofono_gprs *gprs, int attached, ofono_gprs_cb_t cb, void *data) { struct ril_gprs_data *gd = ofono_gprs_get_data(gprs); struct cb_data *cbd; struct parcel rilp; struct gprs_attach_data *attach_data = g_try_new0(struct gprs_attach_data, 1); if (attach_data == NULL) { ofono_error("%s: out of memory", __func__); return; } DBG("attached: %d", attached); attach_data->gd = gd; attach_data->set_attached = attached; cbd = cb_data_new(cb, data, attach_data); /* MTK controls attachment with this request, as opposed to rilmodem */ g_mtk_request_set_gprs_connect_type(gd->ril, attached, &rilp); if (g_ril_send(gd->ril, MTK_RIL_REQUEST_SET_GPRS_CONNECT_TYPE, &rilp, mtk_gprs_set_connect_type_cb, cbd, g_free) == 0) { ofono_error("%s: send failed", __func__); g_free(cbd); CALLBACK_WITH_FAILURE(cb, data); } }
static void cgreg_notify(GAtResult *result, gpointer user_data) { struct ofono_gprs *gprs = user_data; int status; struct gprs_data *gd = ofono_gprs_get_data(gprs); if (at_util_parse_reg_unsolicited(result, "+CGREG:", &status, NULL, NULL, NULL, gd->vendor) == FALSE) return; /* * Telit AT modem firmware (tested with UE910-EUR) generates * +CGREG: 0\r\n\r\n+CGEV: NW DETACH * after a context is de-activated and ppp connection closed. * Then, after a random amount of time (observed from a few seconds * to a few hours), an unsolicited +CGREG: 1 arrives. * Attempt to fix the problem, by sending AT+CGATT=1 once. * This does not re-activate the context, but if a network connection * is still correct, will generate an immediate +CGREG: 1. */ if (gd->vendor == OFONO_VENDOR_TELIT) { if (gd->attached && !status && !gd->telit_try_reattach) { DBG("Trying to re-attach gprs network"); gd->telit_try_reattach = TRUE; g_at_chat_send(gd->chat, "AT+CGATT=1", none_prefix, NULL, NULL, NULL); return; } gd->telit_try_reattach = FALSE; } ofono_gprs_status_notify(gprs, status); }
static void ril_gprs_set_attached(struct ofono_gprs *gprs, int attached, ofono_gprs_cb_t cb, void *data) { struct cb_data *cbd = cb_data_new(cb, data); struct gprs_data *gd = ofono_gprs_get_data(gprs); DBG("attached: %d", attached); /* * As RIL offers no actual control over the GPRS 'attached' * state, we save the desired state, and use it to override * the actual modem's state in the 'attached_status' function. * This is similar to the way the core ofono gprs code handles * data roaming ( see src/gprs.c gprs_netreg_update(). * * The core gprs code calls driver->set_attached() when a netreg * notification is received and any configured roaming conditions * are met. */ gd->notified = (gd->ofono_attached == attached) ? TRUE : FALSE; gd->ofono_attached = attached; cbd->user = gprs; /* * However we cannot respond immediately, since core sets the * value of driver_attached after calling set_attached and that * leads to comparison failure in gprs_attached_update in * connection drop phase */ gd->timer_id = g_timeout_add_seconds(1, ril_gprs_set_attached_callback, cbd); }
static void get_active_data_calls(struct ofono_gprs *gprs) { struct ril_gprs_data *gd = ofono_gprs_get_data(gprs); if (g_ril_send(gd->ril, RIL_REQUEST_DATA_CALL_LIST, NULL, get_active_data_calls_cb, gprs, NULL) == 0) ofono_error("%s: send failed", __func__); }
static void ril_data_probe_reg_cb(struct ril_msg *message, gpointer user_data) { struct cb_data *cbd = user_data; struct ofono_gprs *gprs = cbd->user; struct gprs_data *gd = ofono_gprs_get_data(gprs); struct ofono_error error; int status, lac, ci, tech; int max_cids = 1; int id = RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED; DBG(""); if (!(gd && message->error == RIL_E_SUCCESS)) { ofono_error("ril_data_reg_cb: reply failure: %s", ril_error_to_string(message->error)); decode_ril_error(&error, "FAIL"); error.error = message->error; status = NETWORK_REGISTRATION_STATUS_UNKNOWN; goto out; } decode_ril_error(&error, "OK"); status = -1; if (ril_util_parse_reg(gd->ril, message, &status, &lac, &ci, &tech, &max_cids) == FALSE) { ofono_error("Failure parsing data registration response."); decode_ril_error(&error, "FAIL"); if (status == -1) status = NETWORK_REGISTRATION_STATUS_UNKNOWN; goto out; } ofono_gprs_register(gprs); registered = TRUE; if (max_cids > gd->max_cids) { DBG("Setting max cids to %d", max_cids); gd->max_cids = max_cids; ofono_gprs_set_cid_range(gprs, 1, max_cids); } if (status == NETWORK_REGISTRATION_STATUS_ROAMING) status = check_if_really_roaming(status); out: ofono_info("data registration status is %d", status); DBG("Starting to listen network status"); gd->registerid = g_ril_register(gd->ril, id, ril_gprs_state_change, gprs); gd->rild_status = status; }
static void mtk_gprs_remove(struct ofono_gprs *gprs) { struct ril_gprs_data *gd = ofono_gprs_get_data(gprs); gd->ofono_attached = FALSE; mtk_set_attach_state(gd->modem, gd->ofono_attached); ril_gprs_remove(gprs); }
static void detach_event(struct ril_msg *message, gpointer user_data) { struct ofono_gprs *gprs = user_data; struct ril_gprs_data *gd = ofono_gprs_get_data(gprs); g_ril_print_unsol_no_args(gd->ril, message); mtk_detach_received(gd->modem); }
static void at_cgdcont_test_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_gprs *gprs = user_data; struct gprs_data *gd = ofono_gprs_get_data(gprs); GAtResultIter iter; int min, max; const char *pdp_type; gboolean found = FALSE; if (!ok) goto error; g_at_result_iter_init(&iter, result); while (!found && g_at_result_iter_next(&iter, "+CGDCONT:")) { gboolean in_list = FALSE; if (!g_at_result_iter_open_list(&iter)) continue; if (g_at_result_iter_next_range(&iter, &min, &max) == FALSE) continue; if (!g_at_result_iter_close_list(&iter)) continue; if (g_at_result_iter_open_list(&iter)) in_list = TRUE; if (!g_at_result_iter_next_string(&iter, &pdp_type)) continue; if (in_list && !g_at_result_iter_close_list(&iter)) continue; /* We look for IP PDPs */ if (g_str_equal(pdp_type, "IP")) found = TRUE; } if (found == FALSE) goto error; ofono_gprs_set_cid_range(gprs, min, max); g_at_chat_send(gd->chat, "AT+CGREG=?", cgreg_prefix, at_cgreg_test_cb, gprs, NULL); return; error: ofono_info("GPRS not supported on this device"); ofono_gprs_remove(gprs); }
static void ril_data_reg_cb(struct ril_msg *message, gpointer user_data) { struct cb_data *cbd = user_data; ofono_gprs_status_cb_t cb = cbd->cb; struct ofono_gprs *gprs = cbd->user; struct gprs_data *gd = ofono_gprs_get_data(gprs); struct ofono_error error; int status, lac, ci, tech; int max_cids = 1; if (message->error == RIL_E_SUCCESS) { decode_ril_error(&error, "OK"); } else { ofono_error("ril_data_reg_cb: reply failure: %s", ril_error_to_string(message->error)); decode_ril_error(&error, "FAIL"); error.error = message->error; status = -1; goto error; } if (ril_util_parse_reg(message, &status, &lac, &ci, &tech, &max_cids) == FALSE) { ofono_error("Failure parsing data registration response."); decode_ril_error(&error, "FAIL"); status = -1; goto error; } if (gd->status == -1) { DBG("calling ofono_gprs_register..."); ofono_gprs_register(gprs); g_ril_register(gd->ril, RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, ril_gprs_state_change, gprs); } if (max_cids > gd->max_cids) { DBG("Setting max cids to %d", max_cids); gd->max_cids = max_cids; ofono_gprs_set_cid_range(gprs, 1, max_cids); } if (gd->status != status) { DBG("gd->status: %d status: %d", gd->status, status); ofono_gprs_status_notify(gprs, status); } gd->status = status; gd->tech = tech; error: if (cb) cb(&error, status, cbd->data); }
static gboolean ril_get_status_retry(gpointer user_data) { struct ofono_gprs *gprs = user_data; struct ril_gprs_data *gd = ofono_gprs_get_data(gprs); gd->status_retry_cb_id = 0; ril_gprs_registration_status(gprs, NULL, NULL); return FALSE; }
static void gprs_initialized(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_gprs *gprs = user_data; struct gprs_data *gd = ofono_gprs_get_data(gprs); g_at_chat_register(gd->chat, "+CGEV:", cgev_notify, FALSE, gprs, NULL); g_at_chat_register(gd->chat, "+CGREG:", cgreg_notify, FALSE, gprs, NULL); ofono_gprs_register(gprs); }
static void ril_gprs_remove(struct ofono_gprs *gprs) { struct gprs_data *gd = ofono_gprs_get_data(gprs); DBG(""); ofono_gprs_set_data(gprs, NULL); g_ril_unref(gd->ril); g_free(gd); }
static void at_cgreg_test_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_gprs *gprs = user_data; struct gprs_data *gd = ofono_gprs_get_data(gprs); gint range[2]; GAtResultIter iter; int cgreg1 = 0; int cgreg2 = 0; const char *cmd; if (!ok) goto error; g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+CGREG:")) goto error; if (!g_at_result_iter_open_list(&iter)) goto error; while (g_at_result_iter_next_range(&iter, &range[0], &range[1])) { if (1 >= range[0] && 1 <= range[1]) cgreg1 = 1; if (2 >= range[0] && 2 <= range[1]) cgreg2 = 1; } g_at_result_iter_close_list(&iter); if (cgreg2) cmd = "AT+CGREG=2"; else if (cgreg1) cmd = "AT+CGREG=1"; else goto error; g_at_chat_send(gd->chat, cmd, none_prefix, NULL, NULL, NULL); g_at_chat_send(gd->chat, "AT+CGAUTO=0", none_prefix, NULL, NULL, NULL); /* ST-E modem does not support AT+CGEREP = 2,1 */ if (gd->vendor == OFONO_VENDOR_STE) g_at_chat_send(gd->chat, "AT+CGEREP=1,0", none_prefix, gprs_initialized, gprs, NULL); else g_at_chat_send(gd->chat, "AT+CGEREP=2,1", none_prefix, gprs_initialized, gprs, NULL); return; error: ofono_info("GPRS not supported on this device"); ofono_gprs_remove(gprs); }
static void cgreg_notify(GAtResult *result, gpointer user_data) { struct ofono_gprs *gprs = user_data; int status; struct gprs_data *gd = ofono_gprs_get_data(gprs); if (at_util_parse_reg_unsolicited(result, "+CGREG:", &status, NULL, NULL, NULL, gd->vendor) == FALSE) return; ofono_gprs_status_notify(gprs, status); }
void ril_gprs_remove(struct ofono_gprs *gprs) { struct ril_gprs_data *gd = ofono_gprs_get_data(gprs); DBG(""); if (gd->status_retry_cb_id != 0) g_source_remove(gd->status_retry_cb_id); ofono_gprs_set_data(gprs, NULL); g_ril_unref(gd->ril); g_free(gd); }
static void drop_data_call_cb(struct ril_msg *message, gpointer user_data) { struct ofono_gprs *gprs = user_data; struct ril_gprs_data *gd = ofono_gprs_get_data(gprs); if (message->error == RIL_E_SUCCESS) g_ril_print_response_no_args(gd->ril, message); else ofono_error("%s: RIL error %s", __func__, ril_error_to_string(message->error)); if (--(gd->pending_deact_req) == 0) ril_gprs_registration_status(gprs, NULL, NULL); }
void ril_gprs_set_attached(struct ofono_gprs *gprs, int attached, ofono_gprs_cb_t cb, void *data) { struct cb_data *cbd = cb_data_new(cb, data, NULL); struct ril_gprs_data *gd = ofono_gprs_get_data(gprs); struct gprs_attach_data *attach_data; int attach_aux = attached; DBG("attached: %d", attached); if (g_ril_get_version(gd->ril) < 10) { /* * Older RILs offer no actual control over the GPRS 'attached' * state, we save the desired state, and use it to override * the actual modem's state in the 'attached_status' function. * This is similar to the way the core ofono gprs code handles * data roaming ( see src/gprs.c gprs_netreg_update() ). * * The core gprs code calls driver->set_attached() when a netreg * notificaiton is received and any configured roaming * conditions are met. */ gd->ofono_attached = attached; /* * Call from idle loop, so core can set driver_attached before * the callback is invoked. */ g_idle_add(ril_gprs_set_attached_cb, cbd); return; } attach_data = g_new0(struct gprs_attach_data, 1); attach_data->gd = gd; attach_data->ril = gd->ril; attach_data->set_attached = attached; attach_data->detaching_other_slot = FALSE; /* If we want to attach we have to detach the other slot */ if (attached && ril_get_gril_complement(gd->modem)) { attach_data->ril = ril_get_gril_complement(gd->modem); attach_data->detaching_other_slot = TRUE; attach_aux = !attached; } cbd = cb_data_new(cb, data, attach_data); send_allow_data(cbd, attach_data->ril, attach_aux); }
static void ril_gprs_state_change(struct ril_msg *message, gpointer user_data) { struct ofono_gprs *gprs = user_data; struct ril_gprs_data *gd = ofono_gprs_get_data(gprs); g_ril_print_unsol_no_args(gd->ril, message); /* * We just want to track network data status if ofono * itself is attached, so we avoid unnecessary data state requests. */ if (gd->ofono_attached == TRUE) ril_gprs_registration_status(gprs, NULL, NULL); }
static gboolean ril_fake_response(gpointer user_data) { struct cb_data *cbd = user_data; struct ofono_gprs *gprs = cbd->user; struct gprs_data *gd = ofono_gprs_get_data(gprs); DBG(""); gd->fake_timer_id = 0; ofono_gprs_status_notify(gprs, gd->true_status); g_free(cbd); /* == gd->fake_cbd */ gd->fake_cbd = NULL; return FALSE; }
static void gprs_initialized(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_gprs *gprs = user_data; struct gprs_data *gd = ofono_gprs_get_data(gprs); g_at_chat_register(gd->chat, "+CGEV:", cgev_notify, FALSE, gprs, NULL); g_at_chat_register(gd->chat, "+CGREG:", cgreg_notify, FALSE, gprs, NULL); switch (gd->vendor) { case OFONO_VENDOR_HUAWEI: g_at_chat_register(gd->chat, "^MODE:", huawei_mode_notify, FALSE, gprs, NULL); break; case OFONO_VENDOR_UBLOX: case OFONO_VENDOR_UBLOX_TOBY_L2: g_at_chat_register(gd->chat, "+UREG:", ublox_ureg_notify, FALSE, gprs, NULL); g_at_chat_send(gd->chat, "AT+UREG=1", none_prefix, NULL, NULL, NULL); break; case OFONO_VENDOR_TELIT: g_at_chat_register(gd->chat, "#PSNT:", telit_mode_notify, FALSE, gprs, NULL); g_at_chat_send(gd->chat, "AT#PSNT=1", none_prefix, NULL, NULL, NULL); default: g_at_chat_register(gd->chat, "+CPSB:", cpsb_notify, FALSE, gprs, NULL); g_at_chat_send(gd->chat, "AT+CPSB=1", none_prefix, NULL, NULL, NULL); break; } switch (gd->vendor) { case OFONO_VENDOR_IFX: /* Register for GPRS suspend notifications */ g_at_chat_register(gd->chat, "+XDATASTAT:", xdatastat_notify, FALSE, gprs, NULL); g_at_chat_send(gd->chat, "AT+XDATASTAT=1", none_prefix, NULL, NULL, NULL); break; } ofono_gprs_register(gprs); }
static void ril_gprs_registration_status(struct ofono_gprs *gprs, ofono_gprs_status_cb_t cb, void *data) { struct gprs_data *gd = ofono_gprs_get_data(gprs); struct cb_data *cbd = cb_data_new(cb, data, gprs); DBG(""); if (g_ril_send(gd->ril, RIL_REQUEST_DATA_REGISTRATION_STATE, NULL, ril_data_reg_cb, cbd, g_free) == 0) { ofono_error("%s: send " "RIL_REQUEST_DATA_REGISTRATION_STATE failed", __func__); g_free(cbd); CALLBACK_WITH_FAILURE(cb, -1, data); } }
static void set_ia_apn_cb(struct ril_msg *message, gpointer user_data) { struct cb_data *cbd = user_data; ofono_gprs_cb_t cb = cbd->cb; struct ofono_gprs *gprs = cbd->user; struct ril_gprs_data *gd = ofono_gprs_get_data(gprs); if (message->error != RIL_E_SUCCESS) { ofono_error("%s: reply failure: %s", __func__, ril_error_to_string(message->error)); CALLBACK_WITH_FAILURE(cb, cbd->data); return; } g_ril_print_response_no_args(gd->ril, message); CALLBACK_WITH_SUCCESS(cb, cbd->data); }