static int ril_enable(struct ofono_modem *modem) { struct ril_data *rd = ofono_modem_get_data(modem); DBG(""); rd->ril = g_ril_new("/tmp/rild", OFONO_RIL_VENDOR_AOSP); if (rd->ril == NULL) { ofono_error("g_ril_new() failed to create modem!"); return -EIO; } if (getenv("OFONO_RIL_TRACE")) g_ril_set_trace(rd->ril, TRUE); if (getenv("OFONO_RIL_HEX_TRACE")) g_ril_set_debugf(rd->ril, ril_debug, "IntelModem:"); g_ril_register(rd->ril, RIL_UNSOL_RIL_CONNECTED, ril_connected, modem); g_ril_register(rd->ril, RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, ril_radio_state_changed, modem); return -EINPROGRESS; }
static void ril_stk_agent_ready(struct ofono_stk *stk) { struct stk_data *sd = ofono_stk_get_data(stk); int request = RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING; int ret; DBG(""); if (!subscribed) { DBG("Subscribing notifications"); g_ril_register(sd->ril, RIL_UNSOL_STK_PROACTIVE_COMMAND, ril_stk_pcmd_notify, stk); g_ril_register(sd->ril, RIL_UNSOL_STK_SESSION_END, ril_stk_session_end_notify, stk); g_ril_register(sd->ril, RIL_UNSOL_STK_EVENT_NOTIFY, ril_stk_event_notify, stk); subscribed = TRUE; } /* fire and forget i.e. not waiting for the callback*/ ret = g_ril_send(sd->ril, request, NULL, 0, NULL, NULL, NULL); g_ril_print_request_no_args(sd->ril, ret, request); }
static void start_slot(struct mtk_data *md, struct socket_data *sock, const char *hex_prefix) { ofono_info("Physical slot %d in socket %s", md->slot, sock->path); md->ril = sock->ril; md->radio_state = sock->radio_state; g_ril_set_slot(md->ril, md->slot); if (getenv("OFONO_RIL_TRACE")) g_ril_set_trace(md->ril, TRUE); if (getenv("OFONO_RIL_HEX_TRACE")) g_ril_set_debugf(md->ril, mtk_debug, (char *) hex_prefix); g_ril_set_disconnect_function(md->ril, socket_disconnected, md->modem); g_ril_unregister(sock->ril, sock->radio_state_ev_id); g_ril_register(md->ril, RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, mtk_radio_state_changed, md->modem); mtk_connected(md->modem); }
static void radio_settings_register(const struct ofono_error *error, unsigned int available_rats, void *data) { struct ofono_radio_settings *rs = data; struct radio_data *rd = ofono_radio_settings_get_data(rs); g_ril_register(rd->ril, RIL_UNSOL_RADIO_CAPABILITY, radio_caps_event, rd); rd->gprs_atom_watch = __ofono_modem_add_atom_watch(rd->modem, OFONO_ATOM_TYPE_GPRS, gprs_watch_cb, rs, NULL); /* * If the preferred technology was unknown/unsupported, change to a * valid one (midori can return PREF_NET_TYPE_CDMA_ONLY, for instance). * Changing to anything above GSM can prevent other radios restoring * their settings. */ if (rd->rat_mode == OFONO_RADIO_ACCESS_MODE_ANY) { struct cb_data *cbd = cb_data_new(set_safe_preferred_cb, rd, rd->radio_settings); set_preferred_network(rd, cbd, OFONO_RADIO_ACCESS_MODE_GSM); } /* * We register in all cases, setting FD some times fails until radio is * available (this happens on turbo and maybe in other devices). */ ofono_radio_settings_register(rs); }
static void mtk_post_online(struct ofono_modem *modem) { struct mtk_data *md = ofono_modem_get_data(modem); DBG("slot %d", md->slot); /* With modem powered we can query the type in krillin */ if (g_ril_send(md->ril, MTK_RIL_REQUEST_QUERY_MODEM_TYPE, NULL, query_type_cb, md->modem, NULL) == 0) ofono_error("%s: failure sending QUERY_MODEM_TYPE", __func__); /* Register for changes in SIM insertion */ g_ril_register(md->ril, MTK_RIL_UNSOL_SIM_PLUG_OUT, sim_removed, modem); g_ril_register(md->ril, MTK_RIL_UNSOL_SIM_PLUG_IN, sim_inserted, modem); }
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 gboolean ril_delayed_register(gpointer user_data) { struct ofono_sms *sms = user_data; struct sms_data *data = ofono_sms_get_data(sms); DBG(""); data->timer_id = 0; ofono_sms_register(sms); g_ril_register(data->ril, RIL_UNSOL_RESPONSE_NEW_SMS, ril_sms_notify, sms); g_ril_register(data->ril, RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT, ril_sms_notify, sms); /* This makes the timeout a single-shot */ return FALSE; }
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 int create_gril(struct ofono_modem *modem) { struct ril_data *rd = ofono_modem_get_data(modem); int slot_id = ofono_modem_get_integer(modem, "Slot"); ofono_info("Using %s as socket for slot %d.", RILD_CMD_SOCKET[slot_id], slot_id); /* RIL expects user radio to connect to the socket */ rd->ril = g_ril_new_with_ucred(RILD_CMD_SOCKET[slot_id], OFONO_RIL_VENDOR_AOSP, RADIO_UID, RADIO_GID); /* NOTE: Since AT modems open a tty, and then call * g_at_chat_new(), they're able to return -EIO if * the first fails, and -ENOMEM if the second fails. * in our case, we already return -EIO if the ril_new * fails. If this is important, we can create a ril_socket * abstraction... ( probaby not a bad idea ). */ if (rd->ril == NULL) { ofono_error("g_ril_new() failed to create modem!"); return -EIO; } g_ril_set_slot(rd->ril, slot_id); if (getenv("OFONO_RIL_TRACE")) g_ril_set_trace(rd->ril, TRUE); if (getenv("OFONO_RIL_HEX_TRACE")) g_ril_set_debugf(rd->ril, ril_debug, GRIL_HEX_PREFIX[slot_id]); g_ril_register(rd->ril, RIL_UNSOL_RIL_CONNECTED, ril_connected, modem); g_ril_register(rd->ril, RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, ril_radio_state_changed, modem); return 0; }
static gboolean ril_delayed_register(gpointer user_data) { struct ofono_netreg *netreg = user_data; struct netreg_data *nd = ofono_netreg_get_data(netreg); ofono_netreg_register(netreg); /* Register for network state changes */ g_ril_register(nd->ril, RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, ril_network_state_change, netreg); /* Register for network time update reports */ g_ril_register(nd->ril, RIL_UNSOL_NITZ_TIME_RECEIVED, ril_nitz_notify, netreg); /* Register for signal strength changes */ g_ril_register(nd->ril, RIL_UNSOL_SIGNAL_STRENGTH, ril_strength_notify, netreg); /* This makes the timeout a single-shot */ return FALSE; }
static gboolean ril_delayed_register(gpointer user_data) { struct ofono_cbs *cbs = user_data; struct cbs_data *cd = ofono_cbs_get_data(cbs); ofono_cbs_register(cbs); g_ril_register(cd->ril, RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS, ril_cbs_notify, cbs); return FALSE; }
static gboolean listen_and_get_sim_status(gpointer user) { struct ofono_sim *sim = user; struct sim_data *sd = ofono_sim_get_data(sim); send_get_sim_status(sim); g_ril_register(sd->ril, RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, (GRilNotifyFunc) ril_sim_status_changed, sim); /* TODO: should we also register for RIL_UNSOL_SIM_REFRESH? */ return FALSE; }
static gboolean ril_delayed_register(gpointer user_data) { struct ofono_ussd *ussd = user_data; struct ussd_data *ud = ofono_ussd_get_data(ussd); DBG(""); ofono_ussd_register(ussd); /* Register for USSD responses */ g_ril_register(ud->ril, RIL_UNSOL_ON_USSD, ril_ussd_notify, ussd); return FALSE; }
static int ril_enable(struct ofono_modem *modem) { struct ril_data *ril = ofono_modem_get_data(modem); DBG(""); ril->modem = g_ril_new(RILD_CMD_SOCKET); /* NOTE: Since AT modems open a tty, and then call * g_at_chat_new(), they're able to return -EIO if * the first fails, and -ENOMEM if the second fails. * in our case, we already return -EIO if the ril_new * fails. If this is important, we can create a ril_socket * abstraction... ( probaby not a bad idea ). */ if (ril->modem == NULL) { DBG("g_ril_new() failed to create modem!"); return -EIO; } if (getenv("OFONO_RIL_TRACE")) g_ril_set_trace(ril->modem, TRUE); if (getenv("OFONO_RIL_HEX_TRACE")) g_ril_set_debugf(ril->modem, ril_debug, "Device: "); g_ril_register(ril->modem, RIL_UNSOL_RIL_CONNECTED, ril_connected, modem); g_ril_register(ril->modem, RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, ril_radio_state_changed, modem); ofono_devinfo_create(modem, 0, RILMODEM, ril->modem); return -EINPROGRESS; }
static gboolean ril_delayed_register(gpointer user_data) { struct ofono_sms *sms = user_data; struct sms_data *data = ofono_sms_get_data(sms); DBG(""); ofono_sms_register(sms); /* register to receive INCOMING_SMS */ g_ril_register(data->ril, RIL_UNSOL_RESPONSE_NEW_SMS, ril_sms_notify, sms); /* This makes the timeout a single-shot */ return FALSE; }
static gboolean ril_delayed_register(gpointer user_data) { struct ofono_voicecall *vc = user_data; struct voicecall_data *vd = ofono_voicecall_get_data(vc); ofono_voicecall_register(vc); /* Initialize call list */ poll_clcc(vc); /* Unsol when call state changes */ g_ril_register(vd->ril, RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, ril_call_state_notify, vc); /* This makes the timeout a single-shot */ return FALSE; }
static int ril_gprs_context_probe(struct ofono_gprs_context *gc, unsigned int vendor, void *data) { GRil *ril = data; struct gprs_context_data *gcd; gcd = g_try_new0(struct gprs_context_data, 1); if (gcd == NULL) return -ENOMEM; gcd->ril = g_ril_clone(ril); set_context_disconnected(gcd); ofono_gprs_context_set_data(gc, gcd); gcd->regid = -1; gcd->regid = g_ril_register(gcd->ril, RIL_UNSOL_DATA_CALL_LIST_CHANGED, ril_gprs_context_call_list_changed, gc); return 0; }
static int create_gril(struct ofono_modem *modem) { DBG(" modem: %p", modem); struct ril_data *ril = ofono_modem_get_data(modem); /* RIL expects user radio */ ril_switchUser(); char *path = ril_socket_path(); ril->modem = g_ril_new(path); g_free(path); path = NULL; g_ril_set_disconnect_function(ril->modem, gril_disconnected, modem); /* NOTE: Since AT modems open a tty, and then call * g_at_chat_new(), they're able to return -EIO if * the first fails, and -ENOMEM if the second fails. * in our case, we already return -EIO if the ril_new * fails. If this is important, we can create a ril_socket * abstraction... ( probaby not a bad idea ). */ if (ril->modem == NULL) { DBG("g_ril_new() failed to create modem!"); return -EIO; } if (getenv("OFONO_RIL_TRACE")) g_ril_set_trace(ril->modem, TRUE); if (getenv("OFONO_RIL_HEX_TRACE")) g_ril_set_debugf(ril->modem, ril_debug, "Device: "); g_ril_register(ril->modem, RIL_UNSOL_RIL_CONNECTED, ril_connected, modem); ofono_devinfo_create(modem, 0, "rilmodem", ril->modem); return 0; }
static int mtk_gprs_probe(struct ofono_gprs *gprs, unsigned int vendor, void *data) { struct ril_gprs_driver_data *driver_data = data; struct ril_gprs_data *gd; gd = g_try_new0(struct ril_gprs_data, 1); if (gd == NULL) return -ENOMEM; ril_gprs_start(driver_data, gprs, gd); /* * In MTK the event emitted when the gprs state changes is different * from the one in AOSP ril. Overwrite the one set in parent. */ gd->state_changed_unsol = MTK_RIL_UNSOL_RESPONSE_PS_NETWORK_STATE_CHANGED; g_ril_register(gd->ril, MTK_RIL_UNSOL_GPRS_DETACH, detach_event, gprs); return 0; }
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 ril_gprs_data *gd = ofono_gprs_get_data(gprs); struct reply_data_reg_state *reply; gboolean attached = FALSE; gboolean notify_status = FALSE; int old_status; old_status = gd->rild_status; if (message->error != RIL_E_SUCCESS) { ofono_error("%s: DATA_REGISTRATION_STATE reply failure: %s", __func__, ril_error_to_string(message->error)); goto error; } if ((reply = g_ril_reply_parse_data_reg_state(gd->ril, message)) == NULL) goto error; /* * There are three cases that can result in this callback * running: * * 1) The driver's probe() method was called, and thus an * internal call to ril_gprs_registration_status() is * generated. No ofono cb exists. * * 2) ril_gprs_state_change() is called due to an unsolicited * event from RILD. No ofono cb exists. * * 3) The ofono code code calls the driver's attached_status() * function. A valid ofono cb exists. */ if (gd->rild_status != reply->reg_state.status) { gd->rild_status = reply->reg_state.status; if (cb == NULL) notify_status = TRUE; } /* * Override the actual status based upon the desired * attached status set by the core GPRS code ( controlled * by the ConnnectionManager's 'Powered' property ). */ attached = (reply->reg_state.status == NETWORK_REGISTRATION_STATUS_REGISTERED || reply->reg_state.status == NETWORK_REGISTRATION_STATUS_ROAMING); if (attached && gd->ofono_attached == FALSE) { DBG("attached=true; ofono_attached=false; return !REGISTERED"); reply->reg_state.status = NETWORK_REGISTRATION_STATUS_NOT_REGISTERED; /* * Further optimization so that if ril_status == * NOT_REGISTERED, ofono_attached == false, and status == * ROAMING | REGISTERED, then notify gets cleared... * * As is, this results in unecessary status notify calls * when nothing has changed. */ if (notify_status && reply->reg_state.status == old_status) notify_status = FALSE; } if (old_status == -1) { ofono_gprs_register(gprs); /* Different rild implementations use different events here */ g_ril_register(gd->ril, gd->state_changed_unsol, ril_gprs_state_change, gprs); if (reply->max_cids == 0) gd->max_cids = RIL_MAX_NUM_ACTIVE_DATA_CALLS; else if (reply->max_cids < RIL_MAX_NUM_ACTIVE_DATA_CALLS) gd->max_cids = reply->max_cids; else gd->max_cids = RIL_MAX_NUM_ACTIVE_DATA_CALLS; DBG("Setting max cids to %d", gd->max_cids); ofono_gprs_set_cid_range(gprs, 1, gd->max_cids); /* * This callback is a result of the inital call * to probe(), so should return after registration. */ g_free(reply); return; } /* Just need to notify ofono if it's already attached */ if (notify_status) { /* * If network disconnect has occurred, call detached_notify() * instead of status_notify(). */ if (!attached && (old_status == NETWORK_REGISTRATION_STATUS_REGISTERED || old_status == NETWORK_REGISTRATION_STATUS_ROAMING)) { DBG("calling ofono_gprs_detached_notify()"); ofono_gprs_detached_notify(gprs); reply->reg_state.tech = RADIO_TECH_UNKNOWN; } else { DBG("calling ofono_gprs_status_notify()"); ofono_gprs_status_notify(gprs, reply->reg_state.status); } } if (gd->tech != reply->reg_state.tech) { gd->tech = reply->reg_state.tech; ofono_gprs_bearer_notify(gprs, ril_tech_to_bearer_tech(reply->reg_state.tech)); } if (cb) CALLBACK_WITH_SUCCESS(cb, reply->reg_state.status, cbd->data); g_free(reply); return; error: /* * For some modems DATA_REGISTRATION_STATE will return an error until we * are registered in the voice network. */ if (old_status == -1 && message->error == RIL_E_GENERIC_FAILURE) gd->status_retry_cb_id = g_timeout_add(GET_STATUS_TIMER_MS, ril_get_status_retry, gprs); if (cb) CALLBACK_WITH_FAILURE(cb, -1, cbd->data); }
static int create_gril(struct ofono_modem *modem) { struct mtk_data *md = ofono_modem_get_data(modem); struct socket_data *sock; int sock_num; DBG("slot %d", md->slot); if (md->ril != NULL) return 0; sock = g_try_malloc0(sizeof(*sock)); if (sock == NULL) { ofono_error("%s: Cannot allocate socket_data", __func__); return -ENOMEM; } if (md->slot == MULTISIM_SLOT_0) { sock_num = SOCKET_NUM_FOR_DBG_0; sock->path = sock_slot_0; } else { sock_num = SOCKET_NUM_FOR_DBG_1; sock->path = sock_slot_1; } /* Opens the socket to RIL */ sock->ril = g_ril_new(sock->path, OFONO_RIL_VENDOR_MTK); /* * NOTE: Since AT modems open a tty, and then call * g_at_chat_new(), they're able to return -EIO if * the first fails, and -ENOMEM if the second fails. * in our case, we already return -EIO if the ril_new * fails. If this is important, we can create a ril_socket * abstraction... ( probaby not a bad idea ). */ if (sock->ril == NULL) { ofono_error("g_ril_new() failed to connect to %s!", sock->path); g_free(sock); return -EIO; } else if (md->slot == MULTISIM_SLOT_0) { sock_0 = sock; } else { sock_1 = sock; } sock->radio_state = RADIO_STATE_UNAVAILABLE; sock->radio_state_ev_id = g_ril_register(sock->ril, RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, radio_state_changed, sock); g_ril_register(sock->ril, MTK_RIL_UNSOL_RESPONSE_PLMN_CHANGED, plmn_changed, modem); g_ril_register(sock->ril, MTK_RIL_UNSOL_RESPONSE_REGISTRATION_SUSPENDED, reg_suspended, modem); /* sock_num is negative to avoid confusion with physical slots */ g_ril_set_slot(sock->ril, sock_num); g_ril_set_vendor_print_msg_id_funcs(sock->ril, mtk_request_id_to_string, mtk_unsol_request_to_string); if (getenv("OFONO_RIL_TRACE")) g_ril_set_trace(sock->ril, TRUE); if (getenv("OFONO_RIL_HEX_TRACE")) g_ril_set_debugf(sock->ril, mtk_debug, (char *) sock->path); return 0; }
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; gboolean attached; 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(gd->ril, 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->rild_status == -1) { ofono_gprs_register(gprs); /* RILD tracks data network state together with voice */ 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); } /* We need to notify core always to cover situations when * connection drops temporarily for example when user is * taking CS voice call from LTE or changing technology * preference */ if (gd->rild_status != status) ofono_gprs_status_notify(gprs, status); gd->rild_status = status; /* * Override the actual status based upon the desired * attached status set by the core GPRS code ( controlled * by the ConnnectionManager's 'Powered' property ). */ attached = (status == NETWORK_REGISTRATION_STATUS_REGISTERED || status == NETWORK_REGISTRATION_STATUS_ROAMING); if (attached && gd->ofono_attached == FALSE) { DBG("attached=true; ofono_attached=false; return !REGISTERED"); status = NETWORK_REGISTRATION_STATUS_NOT_REGISTERED; } error: if (cb) cb(&error, status, cbd->data); }
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 ril_gprs_data *gd = ofono_gprs_get_data(gprs); struct reply_data_reg_state *reply; gboolean attached = FALSE; gboolean notify_status = FALSE; int old_status; old_status = gd->rild_status; if (message->error == RIL_E_SUCCESS) { reply = g_ril_reply_parse_data_reg_state(gd->ril, message); if (reply == NULL) { if (cb) CALLBACK_WITH_FAILURE(cb, -1, cbd->data); return; } } else { /* * If we get a RIL error (say, radio not available) it is better * to return unknown values than to call cb with failure status. * If we do the last, ConnectionManager would not be created if * this is the first time we retrieve data status, or we can * even create infinite loops as the status in gprs atom would * not be refreshed. When we finally register we will get events * so we will try to retrieve data state again. */ ofono_error("%s: DATA_REGISTRATION_STATE reply failure: %s", __func__, ril_error_to_string(message->error)); reply = g_malloc0(sizeof(*reply)); reply->reg_state.status = NETWORK_REGISTRATION_STATUS_UNKNOWN; reply->reg_state.tech = RADIO_TECH_UNKNOWN; } /* * There are three cases that can result in this callback * running: * * 1) The driver's probe() method was called, and thus an * internal call to ril_gprs_registration_status() is * generated. No ofono cb exists. * * 2) ril_gprs_state_change() is called due to an unsolicited * event from RILD. No ofono cb exists. * * 3) The ofono code code calls the driver's attached_status() * function. A valid ofono cb exists. */ if (gd->rild_status != reply->reg_state.status) { gd->rild_status = reply->reg_state.status; if (cb == NULL) notify_status = TRUE; } /* * Override the actual status based upon the desired * attached status set by the core GPRS code ( controlled * by the ConnnectionManager's 'Powered' property ). */ attached = (reply->reg_state.status == NETWORK_REGISTRATION_STATUS_REGISTERED || reply->reg_state.status == NETWORK_REGISTRATION_STATUS_ROAMING); if (attached && gd->ofono_attached == FALSE) { DBG("attached=true; ofono_attached=false; return !REGISTERED"); reply->reg_state.status = NETWORK_REGISTRATION_STATUS_NOT_REGISTERED; /* * Further optimization so that if ril_status == * NOT_REGISTERED, ofono_attached == false, and status == * ROAMING | REGISTERED, then notify gets cleared... * * As is, this results in unecessary status notify calls * when nothing has changed. */ if (notify_status && reply->reg_state.status == old_status) notify_status = FALSE; } if (old_status == -1) { ofono_gprs_register(gprs); /* Different rild implementations use different events here */ g_ril_register(gd->ril, gd->state_changed_unsol, ril_gprs_state_change, gprs); if (reply->max_cids == 0) gd->max_cids = RIL_MAX_NUM_ACTIVE_DATA_CALLS; else if (reply->max_cids < RIL_MAX_NUM_ACTIVE_DATA_CALLS) gd->max_cids = reply->max_cids; else gd->max_cids = RIL_MAX_NUM_ACTIVE_DATA_CALLS; DBG("Setting max cids to %d", gd->max_cids); ofono_gprs_set_cid_range(gprs, 1, gd->max_cids); /* * This callback is a result of the inital call * to probe(), so should return after registration. */ g_free(reply); return; } /* Just need to notify ofono if it's already attached */ if (notify_status) { /* * If network disconnect has occurred, call detached_notify() * instead of status_notify(). */ if (!attached && (old_status == NETWORK_REGISTRATION_STATUS_REGISTERED || old_status == NETWORK_REGISTRATION_STATUS_ROAMING)) { DBG("calling ofono_gprs_detached_notify()"); ofono_gprs_detached_notify(gprs); reply->reg_state.tech = RADIO_TECH_UNKNOWN; } else { DBG("calling ofono_gprs_status_notify()"); ofono_gprs_status_notify(gprs, reply->reg_state.status); } } gd->tech = reply->reg_state.tech; ofono_gprs_bearer_notify(gprs, ril_tech_to_bearer_tech(reply->reg_state.tech)); if (cb) CALLBACK_WITH_SUCCESS(cb, reply->reg_state.status, cbd->data); g_free(reply); }