diff mbox series

[15/17] lte: Add provisioning support

Message ID 20240130212137.814082-15-denkenz@gmail.com (mailing list archive)
State Superseded
Commit 69adffb51633efcaa6ca9d933fceaf867543be99
Headers show
Series [01/17] umlrunner: Also mount /var/lib as tmpfs | expand

Commit Message

Denis Kenzior Jan. 30, 2024, 9:21 p.m. UTC
If settings do not exist on disk, try to obtain them from the
provisioning database.  This requires for lte atom to wait until the
EFspn has been read from the SIM.  This is accomplished by creating a
sim spn watch and providing a callback.

When the callback is invoked, try to provision settings with the
MCC/MNC/SPN.  If provisioning succeeds, set the settings into the
currently active default_attach_info.  In all cases, forward the
settings to the the driver and register the interface with D-Bus.
---
 src/lte.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 82 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/src/lte.c b/src/lte.c
index d412e15d90f9..433b18956468 100644
--- a/src/lte.c
+++ b/src/lte.c
@@ -37,6 +37,7 @@ 
 
 #include "ofono.h"
 
+#include "provisiondb.h"
 #include "common.h"
 #include "storage.h"
 
@@ -56,8 +57,54 @@  struct ofono_lte {
 	DBusMessage *pending;
 	struct ofono_lte_default_attach_info pending_info;
 	struct ofono_lte_default_attach_info info;
+	unsigned int spn_watch;
 };
 
+static bool provision_default_attach_info(struct ofono_lte *lte,
+						const char *mcc, const char *mnc,
+						const char *spn)
+{
+	struct provision_db_entry *settings;
+	_auto_(l_free) const struct provision_db_entry *ap = NULL;
+	size_t count;
+	size_t i;
+
+	DBG("Provisioning default bearer info with mcc:'%s', mnc:'%s', spn:'%s'",
+			mcc, mnc, spn);
+
+	if (!__ofono_provision_get_settings(mcc, mnc, spn, &settings, &count))
+		return false;
+
+	DBG("Obtained %zu candidates", count);
+
+	for (i = 0; i < count; i++) {
+		if (settings[i].type & OFONO_GPRS_CONTEXT_TYPE_IA) {
+			ap = &settings[i];
+			break;
+		}
+	}
+
+	if (!is_valid_apn(ap->apn))
+		return false;
+
+	if (ap->username && strlen(ap->username) >
+			OFONO_GPRS_MAX_USERNAME_LENGTH)
+		return false;
+
+	if (ap->password && strlen(ap->password) >
+			OFONO_GPRS_MAX_PASSWORD_LENGTH)
+		return false;
+
+	l_strlcpy(lte->info.apn, ap->apn, sizeof(lte->info.apn));
+	l_strlcpy(lte->info.username, ap->username, sizeof(lte->info.username));
+	l_strlcpy(lte->info.password, ap->password, sizeof(lte->info.password));
+	lte->info.proto = ap->proto;
+	lte->info.auth_method = ap->auth_method;
+
+	DBG("Provisioned successfully");
+	return true;
+}
+
 static int lte_load_settings(struct ofono_lte *lte)
 {
 	struct ofono_modem *modem = __ofono_atom_get_modem(lte->atom);
@@ -361,6 +408,11 @@  static void lte_atom_unregister(struct ofono_atom *atom)
 	DBusConnection *conn = ofono_dbus_get_connection();
 	struct ofono_modem *modem = __ofono_atom_get_modem(atom);
 	const char *path = __ofono_atom_get_path(atom);
+	struct ofono_lte *lte = __ofono_atom_get_data(atom);
+	struct ofono_sim *sim = __ofono_atom_find(OFONO_ATOM_TYPE_SIM, modem);
+
+	if (lte->spn_watch)
+		ofono_sim_remove_spn_watch(sim, &lte->spn_watch);
 
 	ofono_modem_remove_interface(modem, OFONO_LTE_INTERFACE);
 	g_dbus_unregister_interface(conn, path, OFONO_LTE_INTERFACE);
@@ -394,11 +446,38 @@  static void lte_init_default_attach_info_cb(const struct ofono_error *error,
 	ofono_lte_finish_register(lte);
 }
 
+static void spn_read_cb(const char *spn, const char *dc, void *data)
+{
+	struct ofono_lte *lte = data;
+	struct ofono_modem *modem = __ofono_atom_get_modem(lte->atom);
+	struct ofono_sim *sim = __ofono_atom_find(OFONO_ATOM_TYPE_SIM, modem);
+
+	ofono_sim_remove_spn_watch(sim, &lte->spn_watch);
+
+	provision_default_attach_info(lte, ofono_sim_get_mcc(sim),
+					ofono_sim_get_mnc(sim), spn);
+
+	if (lte->driver->set_default_attach_info) {
+		lte->driver->set_default_attach_info(lte, &lte->info,
+					lte_init_default_attach_info_cb, lte);
+		return;
+	}
+
+	ofono_lte_finish_register(lte);
+}
+
 void ofono_lte_register(struct ofono_lte *lte)
 {
-	/* No settings, go straight to registering the interface on D-Bus */
-	if (lte_load_settings(lte) < 0)
-		goto finish_register;
+	/* Wait for SPN to be read in order to try provisioning */
+	if (lte_load_settings(lte) < 0) {
+		struct ofono_modem *modem = __ofono_atom_get_modem(lte->atom);
+		struct ofono_sim *sim = __ofono_atom_find(OFONO_ATOM_TYPE_SIM,
+								modem);
+
+		ofono_sim_add_spn_watch(sim, &lte->spn_watch,
+						spn_read_cb, lte, NULL);
+		return;
+	}
 
 	if (lte->driver->set_default_attach_info) {
 		lte->driver->set_default_attach_info(lte, &lte->info,
@@ -406,7 +485,6 @@  void ofono_lte_register(struct ofono_lte *lte)
 		return;
 	}
 
-finish_register:
 	ofono_lte_finish_register(lte);
 }