コード例 #1
0
ファイル: ifx.c プロジェクト: AndriusA/ofono
static void ifx_set_sim_state(struct ifx_data *data, int state)
{
	DBG("state %d", state);

	switch (state) {
	case 0:	/* SIM not present */
	case 6:	/* SIM Error */
	case 8:	/* SIM Technical Problem */
	case 9:	/* SIM Removed */
		ofono_sim_inserted_notify(data->sim, FALSE);
		break;
	case 1:	/* PIN verification needed */
	case 4:	/* PUK verification needed */
	case 5:	/* SIM permanently blocked */
	case 7:	/* ready for attach (+COPS) */
		ofono_sim_inserted_notify(data->sim, TRUE);
		break;
	case 2:	/* PIN verification not needed – Ready */
	case 3:	/* PIN verified – Ready */
		/*
		 * State 3 is handled in the SIM atom driver
		 * while for state 2 we should be waiting for state 7
		 */
		break;
	case 10: /* SIM Reactivating */
	case 11: /* SIM Reactivated */
	case 12: /* SIM SMS Caching Completed */
	case 99: /* SIM State Unknown */
		ofono_warn("Unhandled SIM state %d received", state);
		break;
	default:
		ofono_warn("Unknown SIM state %d received", state);
		break;
	}
}
コード例 #2
0
ファイル: android-wakelock.c プロジェクト: chihchun/ofono
static int android_wakelock_release(struct wakelock *lock)
{
	if (lock == NULL)
		return -EINVAL;

	DBG("lock %p name %s acquisitions %d",
		lock, lock->name, lock->acquisitions);

	if (!lock->acquisitions) {
		ofono_warn("Attempted to release already released lock %s", lock->name);
		return -EINVAL;
	}

	if (lock->acquisitions > 1) {
		lock->acquisitions--;
		DBG("lock %s released acquisitions %d", lock->name, lock->acquisitions);
		return 0;
	}

	if (wakelock_unlock(lock->name) < 0)
		return -EIO;

	lock->acquisitions = 0;

	DBG("lock %s was released", lock->name);

	return 0;
}
コード例 #3
0
ファイル: telit.c プロジェクト: AndriusA/ofono
static void switch_sim_state_status(struct ofono_modem *modem, int status)
{
	struct telit_data *data = ofono_modem_get_data(modem);

	DBG("%p, SIM status: %d", modem, status);

	switch (status) {
	case 0:	/* SIM not inserted */
		if (data->have_sim == TRUE) {
			ofono_sim_inserted_notify(data->sim, FALSE);
			data->have_sim = FALSE;
			data->sms_phonebook_added = FALSE;
		}
		break;
	case 1:	/* SIM inserted */
	case 2:	/* SIM inserted and PIN unlocked */
		if (data->have_sim == FALSE) {
			ofono_sim_inserted_notify(data->sim, TRUE);
			data->have_sim = TRUE;
		}
		break;
	case 3:	/* SIM inserted, SMS and phonebook ready */
		if (data->sms_phonebook_added == FALSE) {
			ofono_phonebook_create(modem, 0, "atmodem", data->chat);
			ofono_sms_create(modem, 0, "atmodem", data->chat);
			data->sms_phonebook_added = TRUE;
		}
		break;
	default:
		ofono_warn("Unknown SIM state %d received", status);
		break;
	}
}
コード例 #4
0
ファイル: ifx.c プロジェクト: AndriusA/ofono
static void shutdown_device(struct ifx_data *data)
{
	int i, fd;

	DBG("");

	if (data->dlc_init_source > 0) {
		g_source_remove(data->dlc_init_source);
		data->dlc_init_source = 0;
	}

	for (i = 0; i < NUM_DLC; i++) {
		if (data->dlcs[i] == NULL)
			continue;

		g_at_chat_unref(data->dlcs[i]);
		data->dlcs[i] = NULL;
	}

	if (data->mux) {
		g_at_mux_shutdown(data->mux);
		g_at_mux_unref(data->mux);
		data->mux = NULL;
		goto done;
	}

	fd = g_io_channel_unix_get_fd(data->device);

	if (ioctl(fd, TIOCSETD, &data->saved_ldisc) < 0)
		ofono_warn("Failed to restore line discipline");

done:
	g_io_channel_unref(data->device);
	data->device = NULL;
}
コード例 #5
0
ファイル: ifx.c プロジェクト: intgr/ofono
static void ifx_set_sim_state(struct ifx_data *data, int state)
{
	DBG("state %d", state);

	switch (state) {
	case 0:	/* SIM not present */
	case 9:	/* SIM Removed */
		if (data->have_sim == TRUE) {
			ofono_sim_inserted_notify(data->sim, FALSE);
			data->have_sim = FALSE;
		}
		break;
	case 1:	/* PIN verification needed */
	case 2:	/* PIN verification not needed – Ready */
	case 3:	/* PIN verified – Ready */
	case 4:	/* PUK verification needed */
	case 5:	/* SIM permanently blocked */
	case 6:	/* SIM Error */
	case 7:	/* ready for attach (+COPS) */
	case 8:	/* SIM Technical Problem */
		if (data->have_sim == FALSE) {
			ofono_sim_inserted_notify(data->sim, TRUE);
			data->have_sim = TRUE;
		}
		break;
	default:
		ofono_warn("Unknown SIM state %d received", state);
		break;
	}
}
コード例 #6
0
static void telit_portcfg_check_cb(gboolean ok, GAtResult *result,
					gpointer user_data)
{
	struct cb_data *cbd = user_data;
	ofono_location_reporting_enable_cb_t cb = cbd->cb;
	struct ofono_location_reporting *lr = cbd->user;
	struct gps_data *gd = ofono_location_reporting_get_data(lr);
	struct ofono_error error;
	int requested_portcfg, current_portcfg;
	GAtResultIter iter;

	DBG("lr=%p ok=%d", lr, ok);

	decode_at_error(&error, g_at_result_final_response(result));

	if (!ok) {
		cb(&error, -1, cbd->data);

		g_free(cbd);
		return;
	}

	g_at_result_iter_init(&iter, result);

	if (!g_at_result_iter_next(&iter, "#PORTCFG:"))
		goto fail;

	if (!g_at_result_iter_next_number(&iter, &requested_portcfg))
		goto fail;

	if (!g_at_result_iter_next_number(&iter, &current_portcfg))
		goto fail;

	if (current_portcfg != 8) {
		ofono_warn("Unable to start GPS, modem configuration invalid");
		ofono_warn("Refer to doc/telit-modem.txt section HE910/GPS");
		goto fail;
	}

	if (g_at_chat_send(gd->chat, "AT$GPSP=1", none_prefix,
				telit_gps_enable_cb, cbd, NULL) > 0)
		return;

fail:
	CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
	g_free(cbd);
}
コード例 #7
0
static int sco_init(void)
{
	GIOChannel *sco_io;
	struct sockaddr_sco saddr;
	struct bt_voice voice;
	int sk;
	socklen_t len;

	sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET | O_NONBLOCK | SOCK_CLOEXEC,
								BTPROTO_SCO);
	if (sk < 0)
		return -errno;

	/* Bind to local address */
	memset(&saddr, 0, sizeof(saddr));
	saddr.sco_family = AF_BLUETOOTH;
	bt_bacpy(&saddr.sco_bdaddr, BDADDR_ANY);

	if (bind(sk, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
		close(sk);
		return -errno;
	}

	if (setsockopt(sk, SOL_BLUETOOTH, BT_DEFER_SETUP,
				&defer_setup, sizeof(defer_setup)) < 0) {
		int err = -errno;
		defer_setup = 0;
		ofono_warn("Can't enable deferred setup: %s (%d)",
						strerror(errno), errno);
		close(sk);
		return err;
	}

	memset(&voice, 0, sizeof(voice));
	len = sizeof(voice);

	if (defer_setup && getsockopt(sk, SOL_BLUETOOTH, BT_VOICE,
						&voice, &len) == 0)
		transparent_sco = TRUE;

	if (listen(sk, 5) < 0) {
		close(sk);
		return -errno;
	}

	sco_io = g_io_channel_unix_new(sk);
	sco_watch = g_io_add_watch(sco_io,
				G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
				sco_accept, NULL);

	g_io_channel_unref(sco_io);

	return 0;
}
コード例 #8
0
ファイル: ifx.c プロジェクト: AndriusA/ofono
static void dlc_disconnect(gpointer user_data)
{
	struct ofono_modem *modem = user_data;
	struct ifx_data *data = ofono_modem_get_data(modem);

	DBG("");

	ofono_warn("Disconnect of modem channel");

	shutdown_device(data);
}
コード例 #9
0
ファイル: gprs.c プロジェクト: endocode/ofono
static void at_cgdcont_read_cb(gboolean ok, GAtResult *result,
				gpointer user_data)
{
	struct ofono_gprs *gprs = user_data;
	struct gprs_data *gd = ofono_gprs_get_data(gprs);
	int activated_cid = gd->last_auto_context_id;
	const char *apn = NULL;
	GAtResultIter iter;

	DBG("ok %d", ok);

	if (!ok) {
		ofono_warn("Can't read CGDCONT contexts.");
		return;
	}

	g_at_result_iter_init(&iter, result);

	while (g_at_result_iter_next(&iter, "+CGDCONT:")) {
		int read_cid;

		if (!g_at_result_iter_next_number(&iter, &read_cid))
			break;

		if (read_cid != activated_cid)
			continue;

		/* ignore protocol */
		g_at_result_iter_skip_next(&iter);

		g_at_result_iter_next_string(&iter, &apn);

		break;
	}

	if (apn)
		ofono_gprs_cid_activated(gprs, activated_cid, apn);
	else
		ofono_warn("cid %u: Received activated but no apn present",
				activated_cid);
}
コード例 #10
0
ファイル: android-wakelock.c プロジェクト: chihchun/ofono
static int android_wakelock_init(void)
{
	if (!file_exists(ANDROID_WAKELOCK_LOCK_PATH)) {
		ofono_warn("System does not support Android wakelocks.");
		return 0;
	}

	if (wakelock_plugin_register("android-wakelock", &driver) < 0) {
		ofono_error("Failed to register wakelock driver");
		return -EIO;
	}

	return 0;
}
コード例 #11
0
ファイル: ril.c プロジェクト: jpakkane/ofono
static void sim_status_cb(struct ril_msg *message, gpointer user_data)
{
	struct ofono_modem *modem = user_data;
	struct ril_data *ril = ofono_modem_get_data(modem);
	struct reply_sim_status *status;

	DBG("");

	if (message->error != RIL_E_SUCCESS) {
		ril->sim_status_retries++;

		ofono_error("GET_SIM_STATUS request failed: %s; retries: %d",
				ril_error_to_string(message->error),
				ril->sim_status_retries);

		if (ril->sim_status_retries < MAX_SIM_STATUS_RETRIES)
			g_timeout_add_seconds(2, sim_status_retry, modem);
		else
			ofono_error("Max retries for GET_SIM_STATUS exceeded!");
	} else {

		if ((status = g_ril_reply_parse_sim_status(ril->modem, message))
				!= NULL) {

			if (status->card_state == RIL_CARDSTATE_PRESENT) {
				DBG("Card PRESENT; num_apps: %d",
					status->num_apps);

				if (!ril->have_sim) {
					DBG("notify SIM inserted");
					ril->have_sim = TRUE;

					ofono_sim_inserted_notify(ril->sim, TRUE);
				}

			} else {
				ofono_warn("Card NOT_PRESENT.");

				if (ril->have_sim) {
					DBG("notify SIM removed");
					ril->have_sim = FALSE;

					ofono_sim_inserted_notify(ril->sim, FALSE);
				}
			}
			g_ril_reply_free_sim_status(status);
		}
	}
}
コード例 #12
0
ファイル: ril.c プロジェクト: CODeRUS/ofono
static void sim_status_cb(struct ril_msg *message, gpointer user_data)
{
	DBG("error=%d", message->error);
	struct ofono_modem *modem = user_data;
	struct ril_data *ril = ofono_modem_get_data(modem);
	struct sim_status status;
	struct sim_app *apps[MAX_UICC_APPS];

	/*
	 * ril.h claims this should NEVER fail!
	 * However this isn't quite true.  So,
	 * on anything other than SUCCESS, we
	 * log an error, and schedule another
	 * GET_SIM_STATUS request.
	 */

	if (message->error != RIL_E_SUCCESS) {
		ril->sim_status_retries++;

		ofono_error("GET_SIM_STATUS reques failed: %d; retries: %d",
				message->error, ril->sim_status_retries);

		if (ril->sim_status_retries < MAX_SIM_STATUS_RETRIES)
			ril->timer_id = g_timeout_add_seconds(2, (GSourceFunc)
							send_get_sim_status,
							(gpointer) modem);
		else
			ofono_error("Max retries for GET_SIM_STATUS exceeded!");
	} else {
		/* Returns TRUE if cardstate == PRESENT */
		if (ril_util_parse_sim_status(ril->modem, message,
						&status, apps)) {

			if (status.num_apps)
				ril_util_free_sim_apps(apps, status.num_apps);
		} else {
			ofono_warn("No SIM card present.");
		}

		/*
		 * We cannot power on modem, but we need to get
		 * certain interfaces up to be able to make emergency calls
		 * in offline mode and without SIM
		 */
		ofono_modem_set_powered(modem, TRUE);
	}
}
コード例 #13
0
ファイル: phonesim.c プロジェクト: jkangas/ofono-1
static void parse_config(void)
{
	GKeyFile *keyfile;
	GError *err = NULL;
	char **modems;
	int i;
	const char *filename;

	char *conf_override = getenv("OFONO_PHONESIM_CONFIG");
	if (conf_override)
		filename = conf_override;
	else
		filename = CONFIGDIR "/phonesim.conf";

	DBG("filename %s", filename);

	keyfile = g_key_file_new();

	g_key_file_set_list_separator(keyfile, ',');

	if (!g_key_file_load_from_file(keyfile, filename, 0, &err)) {
		ofono_warn("Reading of %s failed: %s", filename, err->message);
		g_error_free(err);
		goto done;
	}

	modems = g_key_file_get_groups(keyfile, NULL);

	for (i = 0; modems[i]; i++) {
		struct ofono_modem *modem;

		modem = create_modem(keyfile, modems[i]);
		if (modem == NULL)
			continue;

		modem_list = g_slist_prepend(modem_list, modem);

		ofono_modem_register(modem);
	}

	g_strfreev(modems);

done:
	g_key_file_free(keyfile);
}
コード例 #14
0
ファイル: cdma-netreg.c プロジェクト: AndriusA/ofono
static void serving_system_callback(const struct ofono_error *error,
					const char *sid, void *data)
{
	struct ofono_cdma_netreg *cdma_netreg = data;
	const char *path = __ofono_atom_get_path(cdma_netreg->atom);
	DBusConnection *conn = ofono_dbus_get_connection();

	if (cdma_netreg->status != CDMA_NETWORK_REGISTRATION_STATUS_REGISTERED
			&& cdma_netreg->status !=
				CDMA_NETWORK_REGISTRATION_STATUS_ROAMING)
		return;

	if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
		DBG("Error during serving system query");
		return;
	}

	DBG("Serving system Identifier: %s", sid);

	if (cdma_netreg->sid != NULL && !strcmp(cdma_netreg->sid, sid))
		return;

	g_free(cdma_netreg->provider_name);
	g_free(cdma_netreg->sid);
	cdma_netreg->provider_name = NULL;
	cdma_netreg->sid = g_strdup(sid);

	ofono_dbus_signal_property_changed(conn, path,
				OFONO_CDMA_NETWORK_REGISTRATION_INTERFACE,
				"SystemIdentifier", DBUS_TYPE_STRING,
				&cdma_netreg->sid);

	if (__ofono_cdma_provision_get_name(sid,
				&cdma_netreg->provider_name) == FALSE) {
		ofono_warn("Provider name not found");
		return;
	}

	ofono_dbus_signal_property_changed(conn, path,
				OFONO_CDMA_NETWORK_REGISTRATION_INTERFACE,
				"Name", DBUS_TYPE_STRING,
				&cdma_netreg->provider_name);
}
コード例 #15
0
ファイル: radio-settings.c プロジェクト: morphis/ofono
static void mtk_set_fd_mode_cb(struct ril_msg *message, gpointer user_data)
{
	struct cb_data *cbd = user_data;
	struct set_fd_mode *user = cbd->user;
	struct ofono_radio_settings *rs = user->rst;
	struct radio_data *rsd = ofono_radio_settings_get_data(rs);
	ofono_radio_settings_fast_dormancy_set_cb_t cb = cbd->cb;

	if (message->error == RIL_E_SUCCESS ||
			message->error == RIL_E_RADIO_NOT_AVAILABLE) {

		if (message->error == RIL_E_RADIO_NOT_AVAILABLE)
			ofono_warn("Could not set fast dormancy "
					"as radio is not available");

		g_ril_print_response_no_args(rsd->ril, message);
		ril_set_fast_dormancy(rs, user->on, cb, cbd->data);
	} else {
		CALLBACK_WITH_FAILURE(cb, cbd->data);
	}

	g_free(user);
}
コード例 #16
0
ファイル: grilunsol.c プロジェクト: alfonsosanchezbeato/ofono
static gboolean handle_settings(struct ril_data_call *call, char *type,
				char *ifname, char *raw_ip_addrs,
				char *raw_dns, char *raw_gws)
{
	gboolean result = FALSE;
	int protocol;
	char **dns_addrs = NULL, **gateways = NULL;
	char **ip_addrs = NULL, **split_ip_addr = NULL;

	protocol = ril_protocol_string_to_ofono_protocol(type);
	if (protocol < 0) {
		ofono_error("%s: invalid type(protocol) specified: %s",
				__func__, type);
		goto done;
	}

	if (ifname == NULL || strlen(ifname) == 0) {
		ofono_error("%s: no interface specified: %s",
				__func__, ifname);
		goto done;
	}

	/* Split DNS addresses */
	if (raw_dns)
		dns_addrs = g_strsplit(raw_dns, " ", 3);

	/*
	 * RILD can return multiple addresses; oFono only supports
	 * setting a single IPv4 gateway.
	 */
	if (raw_gws)
		gateways = g_strsplit(raw_gws, " ", 3);

	if (gateways == NULL || g_strv_length(gateways) == 0) {
		ofono_error("%s: no gateways: %s", __func__, raw_gws);
		goto done;
	}

	/* TODO:
	 * RILD can return multiple addresses; oFono only supports
	 * setting a single IPv4 address.  At this time, we only
	 * use the first address.  It's possible that a RIL may
	 * just specify the end-points of the point-to-point
	 * connection, in which case this code will need to
	 * changed to handle such a device.
	 *
	 * For now split into a maximum of three, and only use
	 * the first address for the remaining operations.
	 */
	if (raw_ip_addrs)
		ip_addrs = g_strsplit(raw_ip_addrs, " ", 3);

	if (ip_addrs == NULL || g_strv_length(ip_addrs) == 0) {
		ofono_error("%s: no IP address: %s", __func__, raw_ip_addrs);
		goto done;
	}

	DBG("num ip addrs is: %d", g_strv_length(ip_addrs));

	if (g_strv_length(ip_addrs) > 1)
		ofono_warn("%s: more than one IP addr returned: %s", __func__,
				raw_ip_addrs);
	/*
	 * Note - the address may optionally include a prefix size
	 * ( Eg. "/30" ).  As this confuses NetworkManager, we
	 * explicitly strip any prefix after calculating the netmask.
	 */
	split_ip_addr = g_strsplit(ip_addrs[0], "/", 2);

	if (split_ip_addr == NULL || g_strv_length(split_ip_addr) == 0) {
		ofono_error("%s: invalid IP address field returned: %s",
				__func__, ip_addrs[0]);
		goto done;
	}

	call->protocol = protocol;
	call->ifname = g_strdup(ifname);
	call->ip_addr = g_strdup(split_ip_addr[0]);
	call->dns_addrs = g_strdupv(dns_addrs);
	call->gateways = g_strdupv(gateways);

	result = TRUE;

done:
	if (dns_addrs)
		g_strfreev(dns_addrs);

	if (gateways)
		g_strfreev(gateways);

	if (ip_addrs)
		g_strfreev(ip_addrs);

	if (split_ip_addr)
		g_strfreev(split_ip_addr);


	return result;
}
コード例 #17
0
ファイル: android-apndb.c プロジェクト: jpakkane/ofono
static void toplevel_apndb_start(GMarkupParseContext *context,
					const gchar *element_name,
					const gchar **attribute_names,
					const gchar **attribute_values,
					gpointer userdata, GError **error)
{
	struct apndb_data *apndb = userdata;
	struct apndb_provision_data *ap = NULL;
	int i;
	const gchar *carrier = NULL;
	const gchar *mcc = NULL;
	const gchar *mnc = NULL;
	const gchar *apn = NULL;
	const gchar *username = NULL;
	const gchar *password = NULL;
	const gchar *types = NULL;
	const gchar *protocol = NULL;
	const gchar *mmsproxy = NULL;
	const gchar *mmsport = NULL;
	const gchar *mmscenter = NULL;
	const gchar *mvnomatch = NULL;
	const gchar *mvnotype = NULL;
	enum ofono_gprs_proto proto = OFONO_GPRS_PROTO_IP;
	enum ofono_gprs_context_type type;

	if (!g_str_equal(element_name, "apn"))
		return;

	for (i = 0; attribute_names[i]; i++) {
		if (g_str_equal(attribute_names[i], "carrier"))
			carrier = attribute_values[i];
		else if (g_str_equal(attribute_names[i], "mcc"))
			mcc = attribute_values[i];
		else if (g_str_equal(attribute_names[i], "mnc"))
			mnc = attribute_values[i];
	}

	if (mcc == NULL) {
		android_apndb_g_set_error(context, error, G_MARKUP_ERROR,
					G_MARKUP_ERROR_MISSING_ATTRIBUTE,
					"Missing attribute: mcc");
		return;
	}

	if (mnc == NULL) {
		android_apndb_g_set_error(context, error, G_MARKUP_ERROR,
					G_MARKUP_ERROR_MISSING_ATTRIBUTE,
					"Missing attribute: mnc");
		return;
	}

	if (g_str_equal(mcc, apndb->match_mcc) == FALSE ||
		g_str_equal(mnc, apndb->match_mnc) == FALSE)
		return;

	for (i = 0; attribute_names[i]; i++) {
		if (g_str_equal(attribute_names[i], "apn"))
			apn = attribute_values[i];
		else if (g_str_equal(attribute_names[i], "user"))
			username = attribute_values[i];
		else if (g_str_equal(attribute_names[i], "password"))
			password = attribute_values[i];
		else if (g_str_equal(attribute_names[i], "type"))
			types = attribute_values[i];
		else if (g_str_equal(attribute_names[i], "protocol"))
			protocol = attribute_values[i];
		else if (g_str_equal(attribute_names[i], "mmsc"))
			mmscenter = attribute_values[i];
		else if (g_str_equal(attribute_names[i], "mmsproxy"))
			mmsproxy = attribute_values[i];
		else if (g_str_equal(attribute_names[i], "mmsport"))
			mmsport = attribute_values[i];
		else if (g_str_equal(attribute_names[i], "mvno_match_data"))
			mvnomatch = attribute_values[i];
		else if (g_str_equal(attribute_names[i], "mvno_type"))
			mvnotype = attribute_values[i];
	}

	if (apn == NULL) {
		android_apndb_g_set_error(context, error, G_MARKUP_ERROR,
					G_MARKUP_ERROR_MISSING_ATTRIBUTE,
						"APN attribute missing");
		return;
	}

	if (types == NULL) {
		ofono_error("%s: apn for %s missing type attribute", __func__,
				carrier);
		return;
	}

	if (protocol != NULL) {
		if (g_str_equal(protocol, "IP")) {
			proto = OFONO_GPRS_PROTO_IP;
		} else if (g_str_equal(protocol, "IPV6")) {
			proto = OFONO_GPRS_PROTO_IPV6;
		} else if (g_str_equal(protocol, "IPV4V6")) {
			proto = OFONO_GPRS_PROTO_IPV4V6;
		} else {
			ofono_error("%s: APN %s has invalid protocol=%s"
					"attribute", __func__, carrier,
					protocol);
			return;
		}
	}

	if (mvnotype != NULL && mvnomatch != NULL) {

		if (g_str_equal(mvnotype, "imsi")) {
			DBG("APN %s is mvno_type 'imsi'", carrier);

			if (imsi_match(apndb->match_imsi, mvnomatch) == FALSE) {
				DBG("Skipping MVNO 'imsi' APN %s with"
					" match_data: %s",
					carrier, mvnomatch);
				return;
			}
		} else if (g_str_equal(mvnotype, "spn")) {
			DBG("APN %s is mvno_type 'spn'", carrier);

			if (g_str_equal(mvnomatch, apndb->match_spn) == FALSE) {
				DBG("Skipping mvno 'spn' APN %s with"
					" match_data: %s",
					carrier, mvnomatch);
				return;
			}

		} else if (g_str_equal(mvnotype, "gid")) {
			ofono_warn("%s: APN %s is unsupported mvno_type 'gid'",
					__func__, carrier);
			return;
		}
	}

	type = determine_apn_type(types);

	if (type == OFONO_GPRS_CONTEXT_TYPE_ANY ||
		(type == OFONO_GPRS_CONTEXT_TYPE_MMS && mmsproxy == NULL)) {
		DBG("Skipping %s context; types: %s", apn, types);
		return;
	}

	ap = g_try_new0(struct apndb_provision_data, 1);
	if (ap == NULL) {
		ofono_error("%s: out-of-memory trying to provision APN - %s",
				__func__, carrier);
		return;
	}

	ap->gprs_data.type = type;

	if (carrier != NULL)
		ap->gprs_data.name = g_strdup(carrier);

	if (apn != NULL)
		ap->gprs_data.apn = g_strdup(apn);

	if (username != NULL)
		ap->gprs_data.username = g_strdup(username);

	if (password != NULL)
		ap->gprs_data.password = g_strdup(password);

	if (mmscenter != NULL && strlen(mmscenter) > 0)
		ap->gprs_data.message_center = g_strdup(mmscenter);

	if (mmsproxy != NULL && strlen(mmsproxy) > 0) {
		char *tmp = android_apndb_sanitize_ipv4_address(mmsproxy);
		if (tmp != NULL)
			mmsproxy = tmp;

		if (mmsport != NULL)
			ap->gprs_data.message_proxy =
				g_strdup_printf("%s:%s", mmsproxy, mmsport);
		else
			ap->gprs_data.message_proxy = g_strdup(mmsproxy);

		g_free(tmp);
	}

	ap->gprs_data.proto = proto;

	if (mvnotype != NULL) {
		ap->mvno = TRUE;
		apndb->mvno_found = TRUE;
	}

	apndb->apns = g_slist_append(apndb->apns, ap);
}