예제 #1
0
static void at_signal_strength(struct ofono_netreg *netreg,
				ofono_netreg_strength_cb_t cb, void *data)
{
	struct netreg_data *nd = ofono_netreg_get_data(netreg);
	struct cb_data *cbd = cb_data_new(cb, data);

	cbd->user = nd;

	/*
	 * If we defaulted to using CIND, then keep using it,
	 * otherwise fall back to CSQ
	 */
	if (nd->signal_index > 0) {
		if (g_at_chat_send(nd->chat, "AT+CIND?", cind_prefix,
					cind_cb, cbd, g_free) > 0)
			return;
	} else {
		if (g_at_chat_send(nd->chat, "AT+CSQ", csq_prefix,
				csq_cb, cbd, g_free) > 0)
			return;
	}

	g_free(cbd);

	CALLBACK_WITH_FAILURE(cb, -1, data);
}
예제 #2
0
static void ril_register_manual(struct ofono_netreg *netreg,
				const char *mcc, const char *mnc,
				ofono_netreg_register_cb_t cb, void *data)
{
	struct netreg_data *nd = ofono_netreg_get_data(netreg);
	struct cb_data *cbd = cb_data_new(cb, data);
	char buf[OFONO_MAX_MCC_LENGTH + OFONO_MAX_MNC_LENGTH + 1];
	struct parcel rilp;
	int request = RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL;
	int ret;

	/* add *netreg_data to callback */
	cbd->user = nd;

	parcel_init(&rilp);

	/* RIL expects a char * specifying MCCMNC of network to select */
	snprintf(buf, sizeof(buf), "%s%s", mcc, mnc);
	parcel_w_string(&rilp, buf);

	ret = g_ril_send(nd->ril, request,
				rilp.data, rilp.size, ril_register_cb,
				cbd, g_free);
	parcel_free(&rilp);

	g_ril_append_print_buf(nd->ril,	"(%s)", buf);
	g_ril_print_request(nd->ril, ret, request);

	/* In case of error free cbd and return the cb with failure */
	if (ret <= 0) {
		g_free(cbd);
		CALLBACK_WITH_FAILURE(cb, data);
	}
}
예제 #3
0
static void cops_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
	struct cb_data *cbd = user_data;
	struct netreg_data *nd = ofono_netreg_get_data(cbd->user);
	ofono_netreg_operator_cb_t cb = cbd->cb;
	struct ofono_network_operator op;
	GAtResultIter iter;
	int format, tech;
	const char *name;
	struct ofono_error error;

	decode_at_error(&error, g_at_result_final_response(result));

	if (!ok)
		goto error;

	g_at_result_iter_init(&iter, result);

	if (!g_at_result_iter_next(&iter, "+COPS:"))
		goto error;

	g_at_result_iter_skip_next(&iter);

	ok = g_at_result_iter_next_number(&iter, &format);

	if (ok == FALSE || format != 0)
		goto error;

	if (g_at_result_iter_next_string(&iter, &name) == FALSE)
		goto error;

	/* Default to GSM */
	if (g_at_result_iter_next_number(&iter, &tech) == FALSE)
		tech = ACCESS_TECHNOLOGY_GSM;

	strncpy(op.name, name, OFONO_MAX_OPERATOR_NAME_LENGTH);
	op.name[OFONO_MAX_OPERATOR_NAME_LENGTH] = '\0';

	strncpy(op.mcc, nd->mcc, OFONO_MAX_MCC_LENGTH);
	op.mcc[OFONO_MAX_MCC_LENGTH] = '\0';

	strncpy(op.mnc, nd->mnc, OFONO_MAX_MNC_LENGTH);
	op.mnc[OFONO_MAX_MNC_LENGTH] = '\0';

	/* Set to current */
	op.status = 2;
	op.tech = tech;

	DBG("cops_cb: %s, %s %s %d", name, nd->mcc, nd->mnc, tech);

	cb(&error, &op, cbd->data);
	g_free(cbd);

	return;

error:
	cb(&error, NULL, cbd->data);

	g_free(cbd);
}
예제 #4
0
static void ril_nitz_notify(struct ril_msg *message, gpointer user_data)
{
	struct ofono_netreg *netreg = user_data;
	struct netreg_data *nd = ofono_netreg_get_data(netreg);
	int year, mon, mday, hour, min, sec, dst, tzi;
	char tzs, tz[4];
	gchar *nitz;

	if ((nitz = g_ril_unsol_parse_nitz(nd->ril, message)) == NULL)
		goto error;

	sscanf(nitz, "%u/%u/%u,%u:%u:%u%c%u,%u", &year, &mon, &mday,
			&hour, &min, &sec, &tzs, &tzi, &dst);
	sprintf(tz, "%c%d", tzs, tzi);

	nd->time.utcoff = atoi(tz) * 15 * 60;
	nd->time.dst = dst;
	nd->time.sec = sec;
	nd->time.min = min;
	nd->time.hour = hour;
	nd->time.mday = mday;
	nd->time.mon = mon;
	nd->time.year = 2000 + year;

	ofono_netreg_time_notify(netreg, &nd->time);

	g_free(nitz);

	return;

error:
	ofono_error("%s: unable to notify ofono about NITZ", __func__);
}
예제 #5
0
static void qmi_register_manual(struct ofono_netreg *netreg,
				const char *mcc, const char *mnc,
				ofono_netreg_register_cb_t cb, void *user_data)
{
	struct netreg_data *data = ofono_netreg_get_data(netreg);
	struct cb_data *cbd = cb_data_new(cb, user_data);
	struct qmi_nas_param_register_manual_info info;
	struct qmi_param *param;

	DBG("");

	param = qmi_param_new_uint8(QMI_NAS_PARAM_REGISTER_ACTION,
					QMI_NAS_REGISTER_ACTION_MANUAL);
	if (!param)
		goto error;

	info.mcc = atoi(mcc);
	info.mnc = atoi(mnc);
	info.rat = data->current_rat;

	qmi_param_append(param, QMI_NAS_PARAM_REGISTER_MANUAL_INFO,
						sizeof(info), &info);

	if (qmi_service_send(data->nas, QMI_NAS_REGISTER_NET, param,
					register_net_cb, cbd, g_free) > 0)
		return;

	qmi_param_free(param);

error:
	CALLBACK_WITH_FAILURE(cb, cbd->data);

	g_free(cbd);
}
예제 #6
0
static void event_notify(struct qmi_result *result, void *user_data)
{
	struct ofono_netreg *netreg = user_data;
	struct netreg_data *data = ofono_netreg_get_data(netreg);
	const struct qmi_nas_signal_strength *ss;
	const struct qmi_nas_rf_info *rf;
	uint16_t len;

	DBG("");

	ss = qmi_result_get(result, QMI_NAS_NOTIFY_SIGNAL_STRENGTH, &len);
        if (ss) {
		int strength;

		DBG("signal with %d dBm on %d", ss->dbm, ss->rat);

		strength = dbm_to_strength(ss->dbm);

		ofono_netreg_strength_notify(netreg, strength);
	}

	rf = qmi_result_get(result, QMI_NAS_NOTIFY_RF_INFO, &len);
	if (rf) {
		uint8_t i;

		for (i = 0; i < rf->count; i++) {
			DBG("rat %d band %d channel %d", rf->info[i].rat,
					rf->info[i].band, rf->info[i].channel);
		}

		data->current_rat = rf->info[i].rat;
	}
}
예제 #7
0
static void ril_network_state_change(struct ril_msg *message, gpointer user_data)
{
	struct ofono_netreg *netreg = user_data;
	struct netreg_data *nd = ofono_netreg_get_data(netreg);
	struct cb_data *cbd = cb_data_new(ril_creg_notify, netreg);
	int request = RIL_REQUEST_VOICE_REGISTRATION_STATE;
	int ret;

	cbd->user = nd;

	if (message->req != RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED)
		goto error;

	g_ril_print_unsol_no_args(nd->ril, message);

	ret = g_ril_send(nd->ril, request, NULL,
				0, ril_creg_cb, cbd, g_free);

	/* For operator update ofono will use the current_operator cb
	 * so we don't need to probe ril here */

	g_ril_print_request_no_args(nd->ril, ret, request);

	if (ret > 0)
		return;

error:
	ofono_error("Unable to request network state changed");
	g_free(cbd);
}
예제 #8
0
static void hfp_current_operator(struct ofono_netreg *netreg,
				ofono_netreg_operator_cb_t cb, void *data)
{
	struct netreg_data *nd = ofono_netreg_get_data(netreg);
	struct cb_data *cbd = cb_data_new(cb, data);
	gboolean ok;

	if (!cbd)
		goto error;

	cbd->user = netreg;

	ok = g_at_chat_send(nd->chat, "AT+COPS=3,0", NULL,
			NULL, cbd, NULL);

	if (ok)
		ok = g_at_chat_send(nd->chat, "AT+COPS?", cops_prefix,
				cops_cb, cbd, g_free);

	if (ok)
		return;

error:
	CALLBACK_WITH_FAILURE(cb, NULL, data);
}
예제 #9
0
static void qmi_register_auto(struct ofono_netreg *netreg,
				ofono_netreg_register_cb_t cb, void *user_data)
{
	struct netreg_data *data = ofono_netreg_get_data(netreg);
	struct cb_data *cbd = cb_data_new(cb, user_data);
	struct qmi_param *param;

	DBG("");

	param = qmi_param_new_uint8(QMI_NAS_PARAM_REGISTER_ACTION,
					QMI_NAS_REGISTER_ACTION_AUTO);
	if (!param)
		goto error;

	if (qmi_service_send(data->nas, QMI_NAS_REGISTER_NET, param,
					register_net_cb, cbd, g_free) > 0)
		return;

	qmi_param_free(param);

error:
	CALLBACK_WITH_FAILURE(cb, cbd->data);

	g_free(cbd);
}
예제 #10
0
static void ifx_ctzdst_notify(GAtResult *result, gpointer user_data)
{
	struct ofono_netreg *netreg = user_data;
	struct netreg_data *nd = ofono_netreg_get_data(netreg);
	int dst;
	GAtResultIter iter;

	g_at_result_iter_init(&iter, result);

	if (!g_at_result_iter_next(&iter, "+CTZDST:"))
		return;

	if (!g_at_result_iter_next_number(&iter, &dst))
		return;

	DBG("dst %d", dst);

	nd->time.dst = dst;

	if (nd->nitz_timeout > 0) {
		g_source_remove(nd->nitz_timeout);
		nd->nitz_timeout = 0;
	}

	ofono_netreg_time_notify(netreg, &nd->time);
}
예제 #11
0
static void ciev_notify(GAtResult *result, gpointer user_data)
{
	struct ofono_netreg *netreg = user_data;
	struct netreg_data *nd = ofono_netreg_get_data(netreg);
	int strength, ind;
	GAtResultIter iter;

	g_at_result_iter_init(&iter, result);

	if (!g_at_result_iter_next(&iter, "+CIEV:"))
		return;

	if (!g_at_result_iter_next_number(&iter, &ind))
		return;

	if (ind != nd->signal_index)
		return;

	if (!g_at_result_iter_next_number(&iter, &strength))
		return;

	if (strength == nd->signal_invalid)
		strength = -1;
	else
		strength = (strength * 100) / (nd->signal_max - nd->signal_min);

	ofono_netreg_strength_notify(netreg, strength);
}
예제 #12
0
static void at_current_operator(struct ofono_netreg *netreg,
				ofono_netreg_operator_cb_t cb, void *data)
{
	struct netreg_data *nd = ofono_netreg_get_data(netreg);
	struct cb_data *cbd = cb_data_new(cb, data);
	gboolean ok;

	cbd->user = netreg;

	/* Nokia modems have a broken return value for the string
	 * returned for the numeric value. It misses a " at the end.
	 * Trying to read this will stall the parser. So skip it. */
	if (nd->vendor == OFONO_VENDOR_NOKIA) {
		ok = g_at_chat_send(nd->chat, "AT+COPS=3,0", none_prefix,
							NULL, NULL, NULL);

		if (ok)
			ok = g_at_chat_send(nd->chat, "AT+COPS?", cops_prefix,
							cops_cb, cbd, NULL);
	} else {
		ok = g_at_chat_send(nd->chat, "AT+COPS=3,2", none_prefix,
							NULL, NULL, NULL);

		if (ok)
			ok = g_at_chat_send(nd->chat, "AT+COPS?", cops_prefix,
						cops_numeric_cb, cbd, NULL);
	}

	if (ok)
		return;

	g_free(cbd);

	CALLBACK_WITH_FAILURE(cb, NULL, data);
}
예제 #13
0
static void hfp_netreg_remove(struct ofono_netreg *netreg)
{
	struct netreg_data *nd = ofono_netreg_get_data(netreg);

	ofono_netreg_set_data(netreg, NULL);

	g_free(nd);
}
예제 #14
0
static void cnti_query_tech_cb(gboolean ok, GAtResult *result,
						gpointer user_data)
{
	struct tech_query *tq = user_data;
	struct netreg_data *nd = ofono_netreg_get_data(tq->netreg);

	ofono_netreg_status_notify(tq->netreg,
			tq->status, tq->lac, tq->ci, nd->tech);
}
예제 #15
0
static void qmi_current_operator(struct ofono_netreg *netreg,
				ofono_netreg_operator_cb_t cb, void *user_data)
{
	struct netreg_data *data = ofono_netreg_get_data(netreg);

	DBG("");

	CALLBACK_WITH_SUCCESS(cb, &data->operator, user_data);
}
예제 #16
0
static void ril_strength_notify(struct ril_msg *message, gpointer user_data)
{
	struct ofono_netreg *netreg = user_data;
	struct netreg_data *nd = ofono_netreg_get_data(netreg);
	int strength = g_ril_unsol_parse_signal_strength(nd->ril, message,
								nd->tech);

	ofono_netreg_strength_notify(netreg, strength);
}
예제 #17
0
static void ril_network_state_change(struct ril_msg *message, gpointer user_data)
{
	struct ofono_netreg *netreg = user_data;
	struct netreg_data *nd = ofono_netreg_get_data(netreg);

	g_ril_print_unsol_no_args(nd->ril, message);

	ril_registration_status(netreg, NULL, NULL);
}
예제 #18
0
static void option_tech_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
	struct cb_data *cbd = user_data;
	struct ofono_netreg *netreg = cbd->data;
	struct netreg_data *nd = ofono_netreg_get_data(netreg);

	if (ok)
		nd->tech = option_parse_tech(result);
	else
		nd->tech = -1;
}
예제 #19
0
static void at_registration_status(struct ofono_netreg *netreg,
					ofono_netreg_status_cb_t cb,
					void *data)
{
	struct netreg_data *nd = ofono_netreg_get_data(netreg);
	struct cb_data *cbd = cb_data_new(cb, data);

	cbd->user = nd;

	switch (nd->vendor) {
	case OFONO_VENDOR_MBM:
		/*
		 * Send *ERINFO to find out the current tech, it will be
		 * intercepted in mbm_erinfo_notify
		 */
		g_at_chat_send(nd->chat, "AT*ERINFO?", none_prefix,
				NULL, NULL, NULL);
		break;
	case OFONO_VENDOR_GOBI:
		/*
		 * Send *CNTI=0 to find out the current tech, it will be
		 * intercepted in gobi_cnti_notify
		 */
		g_at_chat_send(nd->chat, "AT*CNTI=0", none_prefix,
				NULL, NULL, NULL);
		break;
	case OFONO_VENDOR_NOVATEL:
		/*
		 * Send $CNTI=0 to find out the current tech, it will be
		 * intercepted in nw_cnti_notify
		 */
		g_at_chat_send(nd->chat, "AT$CNTI=0", none_prefix,
				NULL, NULL, NULL);
		break;
	case OFONO_VENDOR_OPTION_HSO:
		/*
		 * Send AT_OCTI?;_OUWCTI? to find out the current tech,
		 * option_tech_cb will call fire CREG? to do the rest.
		 */
		if (g_at_chat_send(nd->chat, "AT_OCTI?;_OUWCTI?",
					option_tech_prefix,
					option_tech_cb, cbd, NULL) == 0)
			nd->tech = -1;
		break;
	}

	if (g_at_chat_send(nd->chat, "AT+CREG?", creg_prefix,
				at_creg_cb, cbd, g_free) > 0)
		return;

	g_free(cbd);

	CALLBACK_WITH_FAILURE(cb, -1, -1, -1, -1, data);
}
예제 #20
0
static gboolean notify_time(gpointer user_data)
{
	struct ofono_netreg *netreg = user_data;
	struct netreg_data *nd = ofono_netreg_get_data(netreg);

	nd->nitz_timeout = 0;

	ofono_netreg_time_notify(netreg, &nd->time);

	return FALSE;
}
예제 #21
0
static void cops_numeric_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
	struct cb_data *cbd = user_data;
	struct netreg_data *nd = ofono_netreg_get_data(cbd->user);
	ofono_netreg_operator_cb_t cb = cbd->cb;
	GAtResultIter iter;
	const char *str;
	int format;
	int len;
	struct ofono_error error;

	decode_at_error(&error, g_at_result_final_response(result));

	if (!ok)
		goto error;

	g_at_result_iter_init(&iter, result);

	if (!g_at_result_iter_next(&iter, "+COPS:"))
		goto error;

	g_at_result_iter_skip_next(&iter);

	ok = g_at_result_iter_next_number(&iter, &format);

	if (ok == FALSE || format != 2)
		goto error;

	if (g_at_result_iter_next_string(&iter, &str) == FALSE)
		goto error;

	len = strspn(str, "0123456789");

	if (len != 5 && len != 6)
		goto error;

	extract_mcc_mnc(str, nd->mcc, nd->mnc);

	DBG("Cops numeric got mcc: %s, mnc: %s", nd->mcc, nd->mnc);

	ok = g_at_chat_send(nd->chat, "AT+COPS=3,0", none_prefix,
					NULL, NULL, NULL);

	if (ok)
		ok = g_at_chat_send(nd->chat, "AT+COPS?", cops_prefix,
					cops_cb, cbd, NULL);

	if (ok)
		return;

error:
	cb(&error, NULL, cbd->data);
	g_free(cbd);
}
예제 #22
0
static void ril_netreg_remove(struct ofono_netreg *netreg)
{
	struct netreg_data *nd = ofono_netreg_get_data(netreg);

	if (nd->nitz_timeout)
		g_source_remove(nd->nitz_timeout);

	ofono_netreg_set_data(netreg, NULL);

	g_ril_unref(nd->ril);
	g_free(nd);
}
예제 #23
0
static void hfp_netreg_remove(struct ofono_netreg *netreg)
{
	struct netreg_data *nd = ofono_netreg_get_data(netreg);

	if (nd->register_source != 0)
		g_source_remove(nd->register_source);

	ofono_netreg_set_data(netreg, NULL);

	g_at_chat_unref(nd->chat);
	g_free(nd);
}
예제 #24
0
static void ril_register_auto(struct ofono_netreg *netreg,
				ofono_netreg_register_cb_t cb, void *data)
{
	struct netreg_data *nd = ofono_netreg_get_data(netreg);
	struct cb_data *cbd = cb_data_new(cb, data, nd);

	if (g_ril_send(nd->ril, RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC, NULL,
			ril_register_cb, cbd, g_free) == 0) {
		g_free(cbd);
		CALLBACK_WITH_FAILURE(cb, data);
	}
}
예제 #25
0
static void ril_list_operators(struct ofono_netreg *netreg,
				ofono_netreg_operator_list_cb_t cb, void *data)
{
	struct netreg_data *nd = ofono_netreg_get_data(netreg);
	struct cb_data *cbd = cb_data_new(cb, data, nd);

	if (g_ril_send(nd->ril, RIL_REQUEST_QUERY_AVAILABLE_NETWORKS, NULL,
			ril_cops_list_cb, cbd, g_free) == 0) {
		g_free(cbd);
		CALLBACK_WITH_FAILURE(cb, 0, NULL, data);
	}
}
예제 #26
0
static void ril_current_operator(struct ofono_netreg *netreg,
				ofono_netreg_operator_cb_t cb, void *data)
{
	struct netreg_data *nd = ofono_netreg_get_data(netreg);
	struct cb_data *cbd = cb_data_new(cb, data, nd);

	if (g_ril_send(nd->ril, RIL_REQUEST_OPERATOR, NULL,
			ril_cops_cb, cbd, g_free) == 0) {
		g_free(cbd);
		CALLBACK_WITH_FAILURE(cb, NULL, data);
	}
}
예제 #27
0
static void ril_strength_notify(struct ril_msg *message, gpointer user_data)
{
	struct ofono_netreg *netreg = user_data;
	struct netreg_data *nd = ofono_netreg_get_data(netreg);
	int strength;

	g_assert(message->req == RIL_UNSOL_SIGNAL_STRENGTH);

	strength = ril_util_get_signal(nd->ril, message);
	ofono_netreg_strength_notify(netreg, strength);

	return;
}
예제 #28
0
static void mbm_erinfo_notify(GAtResult *result, gpointer user_data)
{
	struct ofono_netreg *netreg = user_data;
	struct netreg_data *nd = ofono_netreg_get_data(netreg);
	GAtResultIter iter;
	int mode, gsm, umts;

	g_at_result_iter_init(&iter, result);

	if (g_at_result_iter_next(&iter, "*ERINFO:") == FALSE)
		return;

	if (g_at_result_iter_next_number(&iter, &mode) == FALSE)
		return;

	if (g_at_result_iter_next_number(&iter, &gsm) == FALSE)
		return;

	/*
	 * According to MBM the ERINFO unsolicited response does not contain
	 * the mode parameter, however at least the MD300 does report it.  So
	 * we handle both 2 and 3 argument versions
	 */
	if (g_at_result_iter_next_number(&iter, &umts) == FALSE) {
		gsm = mode;
		umts = gsm;
	}

	ofono_info("network capability: GSM %d UMTS %d", gsm, umts);

	/* Convert to tech values from 27.007 */
	switch (gsm) {
	case 1: /* GSM */
		nd->tech = ACCESS_TECHNOLOGY_GSM;
		break;
	case 2: /* EDGE */
		nd->tech = ACCESS_TECHNOLOGY_GSM_EGPRS;
		break;
	default:
		nd->tech = -1;
	}

	switch (umts) {
	case 1: /* UMTS */
		nd->tech = ACCESS_TECHNOLOGY_UTRAN;
		break;
	case 2: /* UMTS + HSDPA */
		nd->tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA;
		break;
	}
}
예제 #29
0
static void ril_signal_strength(struct ofono_netreg *netreg,
				ofono_netreg_strength_cb_t cb, void *data)
{
	struct netreg_data *nd = ofono_netreg_get_data(netreg);
	struct cb_data *cbd = cb_data_new(cb, data, nd);

	if (g_ril_send(nd->ril, RIL_REQUEST_SIGNAL_STRENGTH, NULL,
			ril_strength_cb, cbd, g_free) == 0) {
		ofono_error("Send RIL_REQUEST_SIGNAL_STRENGTH failed.");

		g_free(cbd);
		CALLBACK_WITH_FAILURE(cb, -1, data);
	}
}
예제 #30
0
static void ss_info_notify(struct qmi_result *result, void *user_data)
{
	struct ofono_netreg *netreg = user_data;
	struct netreg_data *data = ofono_netreg_get_data(netreg);
	int status, lac, cellid, tech;

	DBG("");

	if (!extract_ss_info(result, &status, &lac, &cellid, &tech,
							&data->operator))
		return;

	ofono_netreg_status_notify(netreg, status, lac, cellid, tech);
}