Skip to contentSkip to conversation

add LTE atom

PATCH Applied Dragos Tatulea 2 participants 16 messages Nov 10, 2016 – Nov 11, 2016 Kbuild

v2 of 4 Applied Latest is v4 →

lore
Share & tools
lore
#0 lore raw

v2 cover add LTE atom

This patchset adds a simple LTE atom. It can only set the default APN. But it's meant to be easily extensible in the future.

The atom exposes a per modem D-Bus interface. It also uses the oFono persistent configuration store.

The patchset contains:
* lte atom implementation
* U-Blox Toby L2 lte driver implementation
* script for setting the lte properties

The last patches contain the implementation of the TobyL2 driver. They might sit better in a different patchset maybe.

What is not here:
* Atom is always shown, regardles of technology. This should be filtered out.
* No provisioning support yet.

v2 contains fixes from previous v1 review.

Dragos Tatulea (9):
include: add LTE dbus service define
include: add header file for lte atom
lte: add implementation for LTE atom
build: add lte atom support
test: add script for setting lte atom properties
doc: add lte atom documentation
ubloxmodem: add lte atom driver
build: add support for ublox lte atom driver
plugins: ublox: enable lte driver for tobyl2

 Makefile.am                     |   8 +-
 doc/lte-api.txt                 |  35 ++++
 drivers/ubloxmodem/lte.c        | 154 +++++++++++++++++
 drivers/ubloxmodem/ubloxmodem.c |   3 +
 drivers/ubloxmodem/ubloxmodem.h |   5 +
 include/dbus.h                  |   1 +
 include/lte.h                   |  68 ++++++++
 plugins/ublox.c                 |   3 +
 src/lte.c                       | 369 ++++++++++++++++++++++++++++++++++++++++
 test/set-lte-property           |  26 +++
 10 files changed, 669 insertions(+), 3 deletions(-)
 create mode 100644 doc/lte-api.txt
 create mode 100644 drivers/ubloxmodem/lte.c
 create mode 100644 include/lte.h
 create mode 100644 src/lte.c
 create mode 100755 test/set-lte-property
Signature · 1 line
2.7.4
#1 lore raw

PATCH v2 1/9 include: add LTE dbus service define

---
 include/dbus.h | 1 +
 1 file changed, 1 insertion(+)
include/dbus.h +1 -0
index 99d45d6..cf68ae5 100644
@@ -61,6 +61,7 @@ extern "C" {
 #define OFONO_HANDSFREE_INTERFACE OFONO_SERVICE ".Handsfree"
 #define OFONO_SIRI_INTERFACE OFONO_SERVICE ".Siri"
 #define OFONO_NETMON_INTERFACE OFONO_SERVICE ".NetworkMonitor"
+#define OFONO_LTE_INTERFACE OFONO_SERVICE ".LongTermEvolution"
 
 /* CDMA Interfaces */
 #define OFONO_CDMA_VOICECALL_MANAGER_INTERFACE "org.ofono.cdma.VoiceCallManager"
Signature · 1 line
2.7.4
#2 lore raw

Re: [PATCH 1/9] include: add LTE dbus service define

Hi Dragos,

Quoted 4 lines · Dragos Tatulea
---
  include/dbus.h | 1 +
  1 file changed, 1 insertion(+)

Applied, thanks. I did push some minor fixes afterwards.

Regards,
-Denis

#3 lore raw

PATCH v2 2/9 include: add header file for lte atom

In reply to Dragos Tatulea
---
 include/lte.h | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)
 create mode 100644 include/lte.h
include/lte.h new file +68 -0
new file mode 100644
index 0000000..f437798
@@ -0,0 +1,68 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2016  Endocode AG. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __OFONO_LTE_H
+#define __OFONO_LTE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <ofono/types.h>
+
+struct ofono_lte;
+
+struct ofono_lte_default_attach_info {
+	char apn[OFONO_GPRS_MAX_APN_LENGTH + 1];
+};
+
+typedef void (*ofono_lte_cb_t)(const struct ofono_error *error, void *data);
+
+struct ofono_lte_driver {
+	const char *name;
+	int (*probe)(struct ofono_lte *lte, void *data);
+	void (*remove)(struct ofono_lte *lte);
+	int (*set_default_attach_info)(const struct ofono_lte *lte,
+			struct ofono_lte_default_attach_info *info,
+			ofono_lte_cb_t cb, void *data);
+
+};
+
+int ofono_lte_driver_register(const struct ofono_lte_driver *d);
+
+void ofono_lte_driver_unregister(const struct ofono_lte_driver *d);
+
+struct ofono_lte *ofono_lte_create(struct ofono_modem *modem,
+					const char *driver, void *data);
+
+void ofono_lte_register(struct ofono_lte *lte);
+
+void ofono_lte_remove(struct ofono_lte *lte);
+
+void ofono_lte_set_data(struct ofono_lte *lte, void *data);
+
+void *ofono_lte_get_data(const struct ofono_lte *lte);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Signature · 1 line
2.7.4
#4 lore raw

Re: [PATCH 2/9] include: add header file for lte atom

Hi Dragos,

Quoted 5 lines · Dragos Tatulea
---
  include/lte.h | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1 file changed, 68 insertions(+)

create mode 100644 include/lte.h

Applied, thanks.

Regards,
-Denis

#5 lore raw

PATCH v2 3/9 lte: add implementation for LTE atom

In reply to Dragos Tatulea

This implementation can only get/set the default APN setting. But anything expected for this atom is there:
* D-Bus interface
* sync-ing settings to/from file
* interaction with driver

---
 src/lte.c | 369 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 369 insertions(+)
 create mode 100644 src/lte.c
src/lte.c new file +369 -0
new file mode 100644
index 0000000..ba22dc2
@@ -0,0 +1,369 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2016  Endocode AG. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <gdbus.h>
+
+#include "ofono.h"
+
+#include "common.h"
+#include "log.h"
+#include "gprs-context.h"
+#include "storage.h"
+
+#include "lte.h"
+
+#define SETTINGS_STORE "lte"
+#define SETTINGS_GROUP "Settings"
+#define DEFAULT_APN_KEY "DefaultAccessPointName"
+
+struct ofono_lte {
+	const struct ofono_lte_driver *driver;
+	void *driver_data;
+	struct ofono_atom *atom;
+	char *imsi;
+	GKeyFile *settings;
+	DBusMessage *pending;
+	char old_apn[OFONO_GPRS_MAX_APN_LENGTH+1];
+	struct ofono_lte_default_attach_info info;
+};
+
+static GSList *g_drivers = NULL;
+
+static void lte_load_settings(struct ofono_lte *lte)
+{
+	char *apn;
+
+	if (lte->imsi == NULL)
+		return;
+
+	lte->settings = storage_open(lte->imsi, SETTINGS_STORE);
+
+	if (lte->settings == NULL) {
+		ofono_error("LTE: Can't open settings file, "
+				"changes won't be persistent");
+		return;
+	}
+
+	apn = g_key_file_get_string(lte->settings, SETTINGS_GROUP ,
+					DEFAULT_APN_KEY, NULL);
+	if (apn)
+		strcpy(lte->info.apn, apn);
+}
+
+static DBusMessage *lte_get_properties(DBusConnection *conn,
+					DBusMessage *msg, void *data)
+{
+	struct ofono_lte *lte = data;
+	const char *apn = lte->info.apn;
+	DBusMessage *reply;
+	DBusMessageIter iter;
+	DBusMessageIter dict;
+
+	reply = dbus_message_new_method_return(msg);
+	if (reply == NULL)
+		return NULL;
+
+	dbus_message_iter_init_append(reply, &iter);
+
+	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+					OFONO_PROPERTIES_ARRAY_SIGNATURE,
+					&dict);
+	ofono_dbus_dict_append(&dict, DEFAULT_APN_KEY, DBUS_TYPE_STRING, &apn);
+	dbus_message_iter_close_container(&iter, &dict);
+
+	return reply;
+}
+
+static void lte_set_default_attach_info_cb(const struct ofono_error *error,
+						void *data)
+{
+	struct ofono_lte *lte = data;
+	const char *path = __ofono_atom_get_path(lte->atom);
+	DBusConnection *conn = ofono_dbus_get_connection();
+	DBusMessage *reply;
+	const char *apn = lte->info.apn;
+
+	DBG("%s error %d", path, error->type);
+
+	if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
+		g_strlcpy(lte->info.apn, lte->old_apn,
+				OFONO_GPRS_MAX_APN_LENGTH+1);
+
+		__ofono_dbus_pending_reply(&lte->pending,
+				__ofono_error_failed(lte->pending));
+		return;
+	}
+
+	if (lte->pending == NULL)
+		/* This can happen on first register: it's not a reply to
+		 * anything.
+		 */
+		return;
+
+	if (lte->settings) {
+		if (strlen(lte->info.apn) == 0)
+			/* Clear entry on empty APN. */
+			g_key_file_remove_key(lte->settings, SETTINGS_GROUP,
+						DEFAULT_APN_KEY, NULL);
+		else
+			g_key_file_set_string(lte->settings, SETTINGS_GROUP,
+						DEFAULT_APN_KEY, lte->info.apn);
+
+		storage_sync(lte->imsi, SETTINGS_STORE, lte->settings);
+	}
+
+	reply = dbus_message_new_method_return(lte->pending);
+	__ofono_dbus_pending_reply(&lte->pending, reply);
+	lte->pending = NULL;
+
+	ofono_dbus_signal_property_changed(conn, path,
+					OFONO_CONNECTION_CONTEXT_INTERFACE,
+					DEFAULT_APN_KEY,
+					DBUS_TYPE_STRING, &apn);
+}
+
+static DBusMessage *lte_set_default_apn(struct ofono_lte *lte,
+				DBusConnection *conn, DBusMessage *msg,
+				const char *apn)
+{
+	if (strlen(apn) > OFONO_GPRS_MAX_APN_LENGTH)
+		return __ofono_error_invalid_format(msg);
+
+	if (g_str_equal(apn, lte->info.apn))
+		return dbus_message_new_method_return(msg);
+
+	/* We do care about empty value: it can be used for reset. */
+	if (is_valid_apn(apn) == FALSE && apn[0] != '\0')
+		return __ofono_error_invalid_format(msg);
+
+	if (lte->pending) {
+		/* Can happen on fast succession of calls. */
+		dbus_message_unref(lte->pending);
+		lte->pending = NULL;
+	}
+
+	lte->pending = dbus_message_ref(msg);
+
+	g_strlcpy(lte->old_apn, lte->info.apn, OFONO_GPRS_MAX_APN_LENGTH+1);
+	g_strlcpy(lte->info.apn, apn, OFONO_GPRS_MAX_APN_LENGTH+1);
+
+	lte->driver->set_default_attach_info(lte, &lte->info,
+				lte_set_default_attach_info_cb, lte);
+
+	return NULL;
+}
+
+static DBusMessage *lte_set_property(DBusConnection *conn,
+					DBusMessage *msg, void *data)
+{
+	struct ofono_lte *lte = data;
+	DBusMessageIter iter;
+	DBusMessageIter var;
+	const char *property;
+	const char *str;
+
+	if (!dbus_message_iter_init(msg, &iter))
+		return __ofono_error_invalid_args(msg);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+		return __ofono_error_invalid_args(msg);
+
+	dbus_message_iter_get_basic(&iter, &property);
+	dbus_message_iter_next(&iter);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+		return __ofono_error_invalid_args(msg);
+
+	dbus_message_iter_recurse(&iter, &var);
+
+
+	if (!strcmp(property, DEFAULT_APN_KEY)) {
+		if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
+			return __ofono_error_invalid_args(msg);
+
+		dbus_message_iter_get_basic(&var, &str);
+
+		return lte_set_default_apn(lte, conn, msg, str);
+	}
+
+	return __ofono_error_invalid_args(msg);
+}
+
+static const GDBusMethodTable lte_methods[] = {
+	{ GDBUS_METHOD("GetProperties",
+			NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+			lte_get_properties) },
+	{ GDBUS_ASYNC_METHOD("SetProperty",
+			GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
+			NULL, lte_set_property) },
+	{ }
+};
+
+static const GDBusSignalTable lte_signals[] = {
+	{ GDBUS_SIGNAL("PropertyChanged",
+			GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
+	{ }
+};
+
+static void lte_atom_remove(struct ofono_atom *atom)
+{
+	struct ofono_lte *lte = __ofono_atom_get_data(atom);
+
+	DBG("atom: %p", atom);
+
+	if (lte == NULL)
+		return;
+
+	if (lte->settings) {
+		storage_close(lte->imsi, SETTINGS_STORE, lte->settings, TRUE);
+
+		g_free(lte->imsi);
+		lte->imsi = NULL;
+		lte->settings = NULL;
+	}
+
+	if (lte->driver && lte->driver->remove)
+		lte->driver->remove(lte);
+
+	g_free(lte);
+}
+
+
+struct ofono_lte *ofono_lte_create(struct ofono_modem *modem,
+					const char *driver, void *data)
+{
+	struct ofono_lte *lte;
+	GSList *l;
+
+	if (driver == NULL)
+		return NULL;
+
+	lte = g_try_new0(struct ofono_lte, 1);
+
+	if (lte == NULL)
+		return NULL;
+
+	lte->atom = __ofono_modem_add_atom(modem, OFONO_ATOM_TYPE_LTE,
+						lte_atom_remove, lte);
+
+	for (l = g_drivers; l; l = l->next) {
+		const struct ofono_lte_driver *drv = l->data;
+
+		if (g_strcmp0(drv->name, driver))
+			continue;
+
+		if (drv->probe(lte, data) < 0)
+			continue;
+
+		lte->driver = drv;
+		break;
+	}
+
+	DBG("LTE atom created");
+
+	return lte;
+}
+
+int ofono_lte_driver_register(const struct ofono_lte_driver *d)
+{
+	DBG("driver: %p, name: %s", d, d->name);
+
+	if (d->probe == NULL)
+		return -EINVAL;
+
+	g_drivers = g_slist_prepend(g_drivers, (void *) d);
+
+	return 0;
+}
+
+void ofono_lte_driver_unregister(const struct ofono_lte_driver *d)
+{
+	DBG("driver: %p, name: %s", d, d->name);
+
+	g_drivers = g_slist_remove(g_drivers, (void *) d);
+}
+
+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);
+
+	ofono_modem_remove_interface(modem, OFONO_LTE_INTERFACE);
+	g_dbus_unregister_interface(conn, path, OFONO_LTE_INTERFACE);
+}
+
+void ofono_lte_register(struct ofono_lte *lte)
+{
+	DBusConnection *conn = ofono_dbus_get_connection();
+	struct ofono_modem *modem = __ofono_atom_get_modem(lte->atom);
+	const char *path = __ofono_atom_get_path(lte->atom);
+	struct ofono_sim *sim = __ofono_atom_find(OFONO_ATOM_TYPE_SIM, modem);
+	const char *imsi = ofono_sim_get_imsi(sim);
+
+	if (imsi == NULL) {
+		ofono_error("No sim atom required for registering LTE atom.");	
+		return;
+	}
+
+	lte->imsi = g_strdup(imsi);
+
+	lte_load_settings(lte);
+
+	if (!g_dbus_register_interface(conn, path,
+				OFONO_LTE_INTERFACE,
+				lte_methods, lte_signals, NULL,
+				lte, NULL)) {
+		ofono_error("Could not create %s interface",
+				OFONO_LTE_INTERFACE);
+		return;
+	}
+
+	ofono_modem_add_interface(modem, OFONO_LTE_INTERFACE);
+
+	__ofono_atom_register(lte->atom, lte_atom_unregister);
+
+	lte->driver->set_default_attach_info(lte, &lte->info,
+					lte_set_default_attach_info_cb, lte);
+}
+
+void ofono_lte_remove(struct ofono_lte *lte)
+{
+	__ofono_atom_free(lte->atom);
+}
+
+void ofono_lte_set_data(struct ofono_lte *lte, void *data)
+{
+	lte->driver_data = data;
+}
+
+void *ofono_lte_get_data(const struct ofono_lte *lte)
+{
+	return lte->driver_data;
+}
Signature · 1 line
2.7.4
#6 lore raw

Re: [PATCH 3/9] lte: add implementation for LTE atom

Hi Dragos,

Quoted 44 lines · Dragos Tatulea

This implementation can only get/set the default APN setting. But anything expected for this atom is there:
* D-Bus interface
* sync-ing settings to/from file
* interaction with driver

---
  src/lte.c | 369 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1 file changed, 369 insertions(+)

create mode 100644 src/lte.c

src/lte.c new file +28 -0
new file mode 100644
index 0000000..ba22dc2
@@ -0,0 +1,369 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2016  Endocode AG. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <errno.h>
+

src/lte.c line 36

Quoted 10 lines
src/lte.c new file +8 -0
+#include <glib.h>
+#include <gdbus.h>
+
+#include "ofono.h"
+
+#include "common.h"
 
 
+#include "log.h"
+#include "gprs-context.h"

The above two are already included as part of ofono.h. No need for it here.

src/lte.c line 39

Quoted 3 lines
src/lte.c new file +3 -0
+#include "storage.h"
+
+#include "lte.h"

This should be put into ofono.h. Rule of thumb is that all "public plugin" includes (e.g. in include/ofono/*) should be in ofono.h.

The only includes you should be utilizing are the various utility headers in src/

src/lte.c line 52

Quoted 13 lines
src/lte.c new file +13 -0
+
+#define SETTINGS_STORE "lte"
+#define SETTINGS_GROUP "Settings"
+#define DEFAULT_APN_KEY "DefaultAccessPointName"
+
+struct ofono_lte {
+	const struct ofono_lte_driver *driver;
+	void *driver_data;
+	struct ofono_atom *atom;
+	char *imsi;
+	GKeyFile *settings;
+	DBusMessage *pending;
+	char old_apn[OFONO_GPRS_MAX_APN_LENGTH+1];

doc/coding-style.txt item M3. Generally we do it one of two ways:

1. by using pending_foo variable.
2. By re-parsing the pending message

I'd just use approach #2

Quoted 65 lines
src/lte.c new file +65 -0
+	struct ofono_lte_default_attach_info info;
+};
+
+static GSList *g_drivers = NULL;
+
+static void lte_load_settings(struct ofono_lte *lte)
+{
+	char *apn;
+
+	if (lte->imsi == NULL)
+		return;
+
+	lte->settings = storage_open(lte->imsi, SETTINGS_STORE);
+
+	if (lte->settings == NULL) {
+		ofono_error("LTE: Can't open settings file, "
+				"changes won't be persistent");
+		return;
+	}
+
+	apn = g_key_file_get_string(lte->settings, SETTINGS_GROUP ,
+					DEFAULT_APN_KEY, NULL);
+	if (apn)
+		strcpy(lte->info.apn, apn);
+}
+
+static DBusMessage *lte_get_properties(DBusConnection *conn,
+					DBusMessage *msg, void *data)
+{
+	struct ofono_lte *lte = data;
+	const char *apn = lte->info.apn;
+	DBusMessage *reply;
+	DBusMessageIter iter;
+	DBusMessageIter dict;
+
+	reply = dbus_message_new_method_return(msg);
+	if (reply == NULL)
+		return NULL;
+
+	dbus_message_iter_init_append(reply, &iter);
+
+	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+					OFONO_PROPERTIES_ARRAY_SIGNATURE,
+					&dict);
+	ofono_dbus_dict_append(&dict, DEFAULT_APN_KEY, DBUS_TYPE_STRING, &apn);
+	dbus_message_iter_close_container(&iter, &dict);
+
+	return reply;
+}
+
+static void lte_set_default_attach_info_cb(const struct ofono_error *error,
+						void *data)
+{
+	struct ofono_lte *lte = data;
+	const char *path = __ofono_atom_get_path(lte->atom);
+	DBusConnection *conn = ofono_dbus_get_connection();
+	DBusMessage *reply;
+	const char *apn = lte->info.apn;
+
+	DBG("%s error %d", path, error->type);
+
+	if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
+		g_strlcpy(lte->info.apn, lte->old_apn,
+				OFONO_GPRS_MAX_APN_LENGTH+1);
+

src/lte.c line 127

Quoted 10 lines
src/lte.c new file +10 -0
+		__ofono_dbus_pending_reply(&lte->pending,
+				__ofono_error_failed(lte->pending));
+		return;
+	}
+
+	if (lte->pending == NULL)
+		/* This can happen on first register: it's not a reply to
+		 * anything.
+		 */
+		return;

For the initial set case, lets just have a whole new callback.

So the easy way to get the new APN we just set is to parse the arguments from pending one more time. Since it was already sanity checked prior, you can keep it real simple here.

Quoted 31 lines
src/lte.c new file +31 -0
+
+	if (lte->settings) {
+		if (strlen(lte->info.apn) == 0)
+			/* Clear entry on empty APN. */
+			g_key_file_remove_key(lte->settings, SETTINGS_GROUP,
+						DEFAULT_APN_KEY, NULL);
+		else
+			g_key_file_set_string(lte->settings, SETTINGS_GROUP,
+						DEFAULT_APN_KEY, lte->info.apn);
+
+		storage_sync(lte->imsi, SETTINGS_STORE, lte->settings);
+	}
+
+	reply = dbus_message_new_method_return(lte->pending);
+	__ofono_dbus_pending_reply(&lte->pending, reply);
+	lte->pending = NULL;
+
+	ofono_dbus_signal_property_changed(conn, path,
+					OFONO_CONNECTION_CONTEXT_INTERFACE,
+					DEFAULT_APN_KEY,
+					DBUS_TYPE_STRING, &apn);
+}
+
+static DBusMessage *lte_set_default_apn(struct ofono_lte *lte,
+				DBusConnection *conn, DBusMessage *msg,
+				const char *apn)
+{
+	if (strlen(apn) > OFONO_GPRS_MAX_APN_LENGTH)
+		return __ofono_error_invalid_format(msg);
+
+	if (g_str_equal(apn, lte->info.apn))

src/lte.c line 168

Quoted 10 lines
src/lte.c new file +10 -0
+		return dbus_message_new_method_return(msg);
+
+	/* We do care about empty value: it can be used for reset. */
+	if (is_valid_apn(apn) == FALSE && apn[0] != '\0')
+		return __ofono_error_invalid_format(msg);
+
+	if (lte->pending) {
+		/* Can happen on fast succession of calls. */
+		dbus_message_unref(lte->pending);
+		lte->pending = NULL;

?? Generally we simply return a busy error.

src/lte.c line 174

Quoted 6 lines
src/lte.c new file +6 -0
+	}
+
+	lte->pending = dbus_message_ref(msg);
+
+	g_strlcpy(lte->old_apn, lte->info.apn, OFONO_GPRS_MAX_APN_LENGTH+1);
+	g_strlcpy(lte->info.apn, apn, OFONO_GPRS_MAX_APN_LENGTH+1);

doc/coding-style.txt item M3.

Also, lets not do it this way. Since GetProperties() in between calling SetProperty() and it returning might potentially give erroneous results.

Quoted 21 lines
src/lte.c new file +21 -0
+
+	lte->driver->set_default_attach_info(lte, &lte->info,
+				lte_set_default_attach_info_cb, lte);
+
+	return NULL;
+}
+
+static DBusMessage *lte_set_property(DBusConnection *conn,
+					DBusMessage *msg, void *data)
+{
+	struct ofono_lte *lte = data;
+	DBusMessageIter iter;
+	DBusMessageIter var;
+	const char *property;
+	const char *str;
+
+	if (!dbus_message_iter_init(msg, &iter))
+		return __ofono_error_invalid_args(msg);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+		return __ofono_error_invalid_args(msg);

src/lte.c line 205

Quoted 10 lines
src/lte.c new file +10 -0
+
+	dbus_message_iter_get_basic(&iter, &property);
+	dbus_message_iter_next(&iter);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+		return __ofono_error_invalid_args(msg);
+
+	dbus_message_iter_recurse(&iter, &var);
+
+

Double empty line

Quoted 42 lines
src/lte.c new file +42 -0
+	if (!strcmp(property, DEFAULT_APN_KEY)) {
+		if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
+			return __ofono_error_invalid_args(msg);
+
+		dbus_message_iter_get_basic(&var, &str);
+
+		return lte_set_default_apn(lte, conn, msg, str);
+	}
+
+	return __ofono_error_invalid_args(msg);
+}
+
+static const GDBusMethodTable lte_methods[] = {
+	{ GDBUS_METHOD("GetProperties",
+			NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+			lte_get_properties) },
+	{ GDBUS_ASYNC_METHOD("SetProperty",
+			GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
+			NULL, lte_set_property) },
+	{ }
+};
+
+static const GDBusSignalTable lte_signals[] = {
+	{ GDBUS_SIGNAL("PropertyChanged",
+			GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
+	{ }
+};
+
+static void lte_atom_remove(struct ofono_atom *atom)
+{
+	struct ofono_lte *lte = __ofono_atom_get_data(atom);
+
+	DBG("atom: %p", atom);
+
+	if (lte == NULL)
+		return;
+
+	if (lte->settings) {
+		storage_close(lte->imsi, SETTINGS_STORE, lte->settings, TRUE);
+
+		g_free(lte->imsi);
+		lte->imsi = NULL;

src/lte.c line 257

Quoted 10 lines
src/lte.c new file +10 -0
+		lte->settings = NULL;
+	}
+
+	if (lte->driver && lte->driver->remove)
+		lte->driver->remove(lte);
+
+	g_free(lte);
+}
+
+

double empty line :)

Quoted 86 lines
src/lte.c new file +86 -0
+struct ofono_lte *ofono_lte_create(struct ofono_modem *modem,
+					const char *driver, void *data)
+{
+	struct ofono_lte *lte;
+	GSList *l;
+
+	if (driver == NULL)
+		return NULL;
+
+	lte = g_try_new0(struct ofono_lte, 1);
+
+	if (lte == NULL)
+		return NULL;
+
+	lte->atom = __ofono_modem_add_atom(modem, OFONO_ATOM_TYPE_LTE,
+						lte_atom_remove, lte);
+
+	for (l = g_drivers; l; l = l->next) {
+		const struct ofono_lte_driver *drv = l->data;
+
+		if (g_strcmp0(drv->name, driver))
+			continue;
+
+		if (drv->probe(lte, data) < 0)
+			continue;
+
+		lte->driver = drv;
+		break;
+	}
+
+	DBG("LTE atom created");
+
+	return lte;
+}
+
+int ofono_lte_driver_register(const struct ofono_lte_driver *d)
+{
+	DBG("driver: %p, name: %s", d, d->name);
+
+	if (d->probe == NULL)
+		return -EINVAL;
+
+	g_drivers = g_slist_prepend(g_drivers, (void *) d);
+
+	return 0;
+}
+
+void ofono_lte_driver_unregister(const struct ofono_lte_driver *d)
+{
+	DBG("driver: %p, name: %s", d, d->name);
+
+	g_drivers = g_slist_remove(g_drivers, (void *) d);
+}
+
+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);
+
+	ofono_modem_remove_interface(modem, OFONO_LTE_INTERFACE);
+	g_dbus_unregister_interface(conn, path, OFONO_LTE_INTERFACE);
+}
+
+void ofono_lte_register(struct ofono_lte *lte)
+{
+	DBusConnection *conn = ofono_dbus_get_connection();
+	struct ofono_modem *modem = __ofono_atom_get_modem(lte->atom);
+	const char *path = __ofono_atom_get_path(lte->atom);
+	struct ofono_sim *sim = __ofono_atom_find(OFONO_ATOM_TYPE_SIM, modem);
+	const char *imsi = ofono_sim_get_imsi(sim);
+
+	if (imsi == NULL) {
+		ofono_error("No sim atom required for registering LTE atom.");	
+		return;
+	}
+
+	lte->imsi = g_strdup(imsi);
+
+	lte_load_settings(lte);
+
+	if (!g_dbus_register_interface(conn, path,
+				OFONO_LTE_INTERFACE,
+				lte_methods, lte_signals, NULL,
+				lte, NULL)) {
+		ofono_error("Could not create %s interface",

src/lte.c line 353

Quoted 10 lines
src/lte.c new file +10 -0
+				OFONO_LTE_INTERFACE);
+		return;
+	}
+
+	ofono_modem_add_interface(modem, OFONO_LTE_INTERFACE);
+
+	__ofono_atom_register(lte->atom, lte_atom_unregister);
+
+	lte->driver->set_default_attach_info(lte, &lte->info,
+					lte_set_default_attach_info_cb, lte);

Generally we should register the interface after we have loaded the settings and bootstrapped them into the driver. This will be especially true if we have to run provisioning first. So i would perform the registration steps in a specific callback. e.g. something like:

if (lte->driver->set_default_attach_info) {
	lte->driver->set_default_attach_info(lte, &lte->info, 
init_default_attach_info_cb, lte);
	return;
}

/* otherwise, register the interface, probably by calling a common helper */ ofono_lte_finish_register(...);

Quoted 7 lines
src/lte.c new file +6 -0
+}
+
+void ofono_lte_remove(struct ofono_lte *lte)
+{
+	__ofono_atom_free(lte->atom);
+}

src/lte.c line 369

Quoted 10 lines
src/lte.c new file +10 -0
+
+void ofono_lte_set_data(struct ofono_lte *lte, void *data)
+{
+	lte->driver_data = data;
+}
+
+void *ofono_lte_get_data(const struct ofono_lte *lte)
+{
+	return lte->driver_data;
+}

Regards,
-Denis

#7 lore raw

PATCH v2 4/9 build: add lte atom support

In reply to Dragos Tatulea
---
 Makefile.am | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
Makefile.am +2 -2
index acd5083..9d22365 100644
@@ -22,7 +22,7 @@ pkginclude_HEADERS = include/log.h include/plugin.h include/history.h \
 			include/private-network.h include/cdma-netreg.h \
 			include/cdma-provision.h include/handsfree.h \
 			include/handsfree-audio.h include/siri.h \
-			include/netmon.h
+			include/netmon.h include/lte.h
 
 nodist_pkginclude_HEADERS = include/version.h
 
@@ -605,7 +605,7 @@ src_ofonod_SOURCES = $(builtin_sources) $(gatchat_sources) src/ofono.ver \
 			src/cdma-provision.c src/handsfree.c \
 			src/handsfree-audio.c src/bluetooth.h \
 			src/hfp.h src/siri.c \
-			src/netmon.c
+			src/netmon.c src/lte.c
 
 src_ofonod_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
 			@GLIB_LIBS@ @DBUS_LIBS@ -ldl
Signature · 1 line
2.7.4
#8 lore raw

PATCH v2 5/9 test: add script for setting lte atom properties

In reply to Dragos Tatulea
---
 test/set-lte-property | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
 create mode 100755 test/set-lte-property
test/set-lte-property new file +26 -0
new file mode 100755
index 0000000..a34e60a
@@ -0,0 +1,26 @@
+#!/usr/bin/python3
+
+import dbus
+import sys
+
+bus = dbus.SystemBus()
+
+if len(sys.argv) == 4:
+	path = sys.argv[1]
+	name = sys.argv[2]
+	value = sys.argv[3]
+elif len(sys.argv) == 3:
+	manager = dbus.Interface(bus.get_object('org.ofono', '/'),
+					'org.ofono.Manager')
+	modems = manager.GetModems()
+	path = modems[0][0]
+	name = sys.argv[1]
+	value = sys.argv[2]
+else:
+	print("%s [PATH] name value" % (sys.argv[0]))
+	sys.exit(0)
+
+print("Setting {} as {} for modem {}..." .format(name, value, path))
+lte = dbus.Interface(bus.get_object('org.ofono', path),
+			'org.ofono.LongTermEvolution')
+lte.SetProperty(name, value)
Signature · 1 line
2.7.4
#9 lore raw

Re: [PATCH 5/9] test: add script for setting lte atom properties

Hi Dragos,

Quoted 5 lines · Dragos Tatulea
---
  test/set-lte-property | 26 ++++++++++++++++++++++++++
  1 file changed, 26 insertions(+)

create mode 100755 test/set-lte-property

Applied, thanks.

Regards,
-Denis

#10 lore raw

PATCH v2 6/9 doc: add lte atom documentation

In reply to Dragos Tatulea
---
 doc/lte-api.txt | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 doc/lte-api.txt
doc/lte-api.txt new file +35 -0
new file mode 100644
index 0000000..8a2a97d
@@ -0,0 +1,35 @@
+LongTermEvolution Hierarchy
+
+Service		org.ofono
+Interface	org.ofono.LongTermEvolution
+Object path	[variable prefix]/{modem0,modem1,...}
+
+
+Methods		dict GetProperties()
+
+			Returns all LongTermEvolution configuration properties.
+
+		void SetProperty(string property, variant value)
+
+			Changes the value of the specified property. Only
+			properties that are listed as readwrite are
+			changeable. On success a PropertyChanged signal
+			will be emitted.
+
+			Possible Errors: [service].Error.InProgress
+					 [service].Error.InvalidArguments
+					 [service].Error.Failed
+
+Signals		PropertyChanged(string property, variant value)
+
+			This signal indicates a changed value of the given
+			property.
+
+Properties	string DefaultAccessPointName [readwrite]
+
+			On LongTermEvolution, contexts activate automatically.
+			This property allows selection of an APN to be used on
+			next automatic activation.
+
+			Setting this property to an empty string clears the
+			default APN from the modem.
Signature · 1 line
2.7.4
#11 lore raw

Re: [PATCH 6/9] doc: add lte atom documentation

Hi Dragos,

Quoted 5 lines · Dragos Tatulea
---
  doc/lte-api.txt | 35 +++++++++++++++++++++++++++++++++++
  1 file changed, 35 insertions(+)

create mode 100644 doc/lte-api.txt

Applied, thanks.

Regards,
-Denis

#12 lore raw

PATCH v2 7/9 ubloxmodem: add lte atom driver

In reply to Dragos Tatulea

Adds U-Blox Toby L2 driver for setting the default APN via the +UCGDFLT command. Currently only IPv4 is supported. APN is not stored to modem's non-volatile memory. oFono will manage this default APN via it's config storage.

When receiving an empty default APN, the value is reset.

---
 drivers/ubloxmodem/lte.c        | 154 ++++++++++++++++++++++++++++++++++++++++
 drivers/ubloxmodem/ubloxmodem.c |   3 +
 drivers/ubloxmodem/ubloxmodem.h |   5 ++
 3 files changed, 162 insertions(+)
 create mode 100644 drivers/ubloxmodem/lte.c
drivers/ubloxmodem/lte.c new file +154 -0
new file mode 100644
index 0000000..43c02d4
@@ -0,0 +1,154 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2016  Endocode AG. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <glib.h>
+
+#include <ofono/modem.h>
+#include <ofono/gprs-context.h>
+#include <ofono/log.h>
+#include <ofono/lte.h>
+
+#include "gatchat.h"
+#include "gatresult.h"
+
+#include "ubloxmodem.h"
+
+static const char *ucgdflt_prefix[] = { "+UCGDFLT:", NULL };
+
+struct lte_driver_data {
+	GAtChat *chat;
+};
+
+static void ucgdflt_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_lte_cb_t cb = cbd->cb;
+
+	DBG("ok %d", ok);
+
+	if (!ok) {
+		struct ofono_error error;
+
+		decode_at_error(&error, g_at_result_final_response(result));
+		cb(&error, cbd->data);
+	} else {
+		CALLBACK_WITH_SUCCESS(cb, cbd->data);
+	}
+
+	g_free(cbd);
+
+	return;
+}
+
+static int ublox_lte_set_default_attach_info(const struct ofono_lte *lte,
+				struct ofono_lte_default_attach_info *info,
+				ofono_lte_cb_t cb, void *data)
+{
+	struct lte_driver_data *ldd = ofono_lte_get_data(lte);
+	char buf[32 + OFONO_GPRS_MAX_APN_LENGTH + 1];
+	struct cb_data *cbd = cb_data_new(cb, data);
+
+	DBG("LTE config with APN: %s", info->apn);
+
+	if (strlen(info->apn) > 0)
+		snprintf(buf, sizeof(buf), "AT+UCGDFLT=0,\"IP\",\"%s\"",
+				info->apn);
+	else
+		snprintf(buf, sizeof(buf), "AT+UCGDFLT=0");
+
+	/* We can't do much in case of failure so don't check response. */
+	if (g_at_chat_send(ldd->chat, buf, ucgdflt_prefix,
+				ucgdflt_cb, cbd, NULL) == 0) {
+		g_free(cbd);
+		CALLBACK_WITH_FAILURE(cb, data);
+	}
+
+	return 0;
+}
+
+static gboolean lte_delayed_register(gpointer user_data)
+{
+	struct ofono_lte *lte = user_data;
+
+	ofono_lte_register(lte);
+
+	return FALSE;
+}
+
+static int ublox_lte_probe(struct ofono_lte *lte, void *data)
+{
+	GAtChat *chat = data;
+	struct lte_driver_data *ldd;
+
+	DBG("ublox lte probe");
+
+	ldd = g_try_new0(struct lte_driver_data, 1);
+	if (!ldd) {
+		return -ENOMEM;
+	}
+
+	ldd->chat = g_at_chat_clone(chat);
+
+	ofono_lte_set_data(lte, ldd);
+
+	g_idle_add(lte_delayed_register, lte);
+
+	return 0;
+}
+
+static void ublox_lte_remove(struct ofono_lte *lte)
+{
+	struct lte_driver_data *ldd = ofono_lte_get_data(lte);
+
+	DBG("ublox lte remove");
+
+	g_at_chat_unref(ldd->chat);
+
+	ofono_lte_set_data(lte, NULL);
+
+	g_free(ldd);
+}
+
+static struct ofono_lte_driver driver = {
+	.name				= UBLOXMODEM,
+	.probe				= ublox_lte_probe,
+	.remove				= ublox_lte_remove,
+	.set_default_attach_info	= ublox_lte_set_default_attach_info,
+};
+
+void ublox_lte_init(void)
+{
+	ofono_lte_driver_register(&driver);
+}
+
+void ublox_lte_exit(void)
+{
+	ofono_lte_driver_unregister(&driver);
+}
drivers/ubloxmodem/ubloxmodem.c +3 -0
index 7fc671e..93cb928 100644
@@ -29,12 +29,14 @@
 #define OFONO_API_SUBJECT_TO_CHANGE
 #include <ofono/plugin.h>
 #include <ofono/types.h>
+#include <ofono/modem.h>
 
 #include "ubloxmodem.h"
 
 static int ubloxmodem_init(void)
 {
 	ublox_gprs_context_init();
+	ublox_lte_init();
 
 	return 0;
 }
@@ -42,6 +44,7 @@ static int ubloxmodem_init(void)
 static void ubloxmodem_exit(void)
 {
 	ublox_gprs_context_exit();
+	ublox_lte_exit();
 }
 
 OFONO_PLUGIN_DEFINE(ubloxmodem, "U-Blox Toby L2 high speed modem driver",
drivers/ubloxmodem/ubloxmodem.h +5 -0
index 0c8a621..cf66412 100644
@@ -21,5 +21,10 @@
 
 #include <drivers/atmodem/atutil.h>
 
+#define UBLOXMODEM "ubloxmodem"
+
 extern void ublox_gprs_context_init(void);
 extern void ublox_gprs_context_exit(void);
+
+extern void ublox_lte_init(void);
+extern void ublox_lte_exit(void);
Signature · 1 line
2.7.4
#13 lore raw

Re: [PATCH 7/9] ubloxmodem: add lte atom driver

Hi Dragos,

Quoted 69 lines · Dragos Tatulea

Adds U-Blox Toby L2 driver for setting the default APN via the +UCGDFLT command. Currently only IPv4 is supported. APN is not stored to modem's non-volatile memory. oFono will manage this default APN via it's config storage.

When receiving an empty default APN, the value is reset.

---
  drivers/ubloxmodem/lte.c        | 154 ++++++++++++++++++++++++++++++++++++++++
  drivers/ubloxmodem/ubloxmodem.c |   3 +
  drivers/ubloxmodem/ubloxmodem.h |   5 ++
  3 files changed, 162 insertions(+)

create mode 100644 drivers/ubloxmodem/lte.c

drivers/ubloxmodem/lte.c new file +50 -0
new file mode 100644
index 0000000..43c02d4
@@ -0,0 +1,154 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2016  Endocode AG. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <glib.h>
+
+#include <ofono/modem.h>
+#include <ofono/gprs-context.h>
+#include <ofono/log.h>
+#include <ofono/lte.h>
+
+#include "gatchat.h"
+#include "gatresult.h"
+
+#include "ubloxmodem.h"
+
+static const char *ucgdflt_prefix[] = { "+UCGDFLT:", NULL };
+
+struct lte_driver_data {
+	GAtChat *chat;
+};
+
+static void ucgdflt_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{

drivers/ubloxmodem/lte.c line 60

Quoted 10 lines
drivers/ubloxmodem/lte.c new file +10 -0
+	struct cb_data *cbd = user_data;
+	ofono_lte_cb_t cb = cbd->cb;
+
+	DBG("ok %d", ok);
+
+	if (!ok) {
+		struct ofono_error error;
+
+		decode_at_error(&error, g_at_result_final_response(result));
+		cb(&error, cbd->data);

decode_at_error works for OK responses as well, so there's no need for this if-else statement.

drivers/ubloxmodem/lte.c line 65

Quoted 5 lines
drivers/ubloxmodem/lte.c new file +5 -0
+	} else {
+		CALLBACK_WITH_SUCCESS(cb, cbd->data);
+	}
+
+	g_free(cbd);

This should not be necessary either. See below.

drivers/ubloxmodem/lte.c line 67

Quoted 2 lines
drivers/ubloxmodem/lte.c new file +2 -0
+
+	return;

?? this return is pointless

Quoted 11 lines
drivers/ubloxmodem/lte.c new file +11 -0
+}
+
+static int ublox_lte_set_default_attach_info(const struct ofono_lte *lte,
+				struct ofono_lte_default_attach_info *info,
+				ofono_lte_cb_t cb, void *data)
+{
+	struct lte_driver_data *ldd = ofono_lte_get_data(lte);
+	char buf[32 + OFONO_GPRS_MAX_APN_LENGTH + 1];
+	struct cb_data *cbd = cb_data_new(cb, data);
+
+	DBG("LTE config with APN: %s", info->apn);

drivers/ubloxmodem/lte.c line 88

Quoted 10 lines
drivers/ubloxmodem/lte.c new file +10 -0
+
+	if (strlen(info->apn) > 0)
+		snprintf(buf, sizeof(buf), "AT+UCGDFLT=0,\"IP\",\"%s\"",
+				info->apn);
+	else
+		snprintf(buf, sizeof(buf), "AT+UCGDFLT=0");
+
+	/* We can't do much in case of failure so don't check response. */
+	if (g_at_chat_send(ldd->chat, buf, ucgdflt_prefix,
+				ucgdflt_cb, cbd, NULL) == 0) {

You should be setting the last argument (e.g. GDestroyNotify) as g_free to avoid memory leaks.

drivers/ubloxmodem/lte.c line 91

Quoted 3 lines
drivers/ubloxmodem/lte.c new file +3 -0
+		g_free(cbd);
+		CALLBACK_WITH_FAILURE(cb, data);
+	}

This is far easier to write as:

if (g_at_chat_send(....) > 0)

	return;

CALLBACK_WITH_FAILURE();

drivers/ubloxmodem/lte.c line 93

Quoted 2 lines
drivers/ubloxmodem/lte.c new file +2 -0
+
+	return 0;

Only probe() can return error values. All other methods should return void. I pushed a fix to include/lte.h to reflect this.

Quoted 94 lines
drivers/ubloxmodem/lte.c new file +61 -0
+}
+
+static gboolean lte_delayed_register(gpointer user_data)
+{
+	struct ofono_lte *lte = user_data;
+
+	ofono_lte_register(lte);
+
+	return FALSE;
+}
+
+static int ublox_lte_probe(struct ofono_lte *lte, void *data)
+{
+	GAtChat *chat = data;
+	struct lte_driver_data *ldd;
+
+	DBG("ublox lte probe");
+
+	ldd = g_try_new0(struct lte_driver_data, 1);
+	if (!ldd) {
+		return -ENOMEM;
+	}
+
+	ldd->chat = g_at_chat_clone(chat);
+
+	ofono_lte_set_data(lte, ldd);
+
+	g_idle_add(lte_delayed_register, lte);
+
+	return 0;
+}
+
+static void ublox_lte_remove(struct ofono_lte *lte)
+{
+	struct lte_driver_data *ldd = ofono_lte_get_data(lte);
+
+	DBG("ublox lte remove");
+
+	g_at_chat_unref(ldd->chat);
+
+	ofono_lte_set_data(lte, NULL);
+
+	g_free(ldd);
+}
+
+static struct ofono_lte_driver driver = {
+	.name				= UBLOXMODEM,
+	.probe				= ublox_lte_probe,
+	.remove				= ublox_lte_remove,
+	.set_default_attach_info	= ublox_lte_set_default_attach_info,
+};
+
+void ublox_lte_init(void)
+{
+	ofono_lte_driver_register(&driver);
+}
+
+void ublox_lte_exit(void)
+{
+	ofono_lte_driver_unregister(&driver);
+}
drivers/ubloxmodem/ubloxmodem.c +3 -0
index 7fc671e..93cb928 100644
@@ -29,12 +29,14 @@
  #define OFONO_API_SUBJECT_TO_CHANGE
  #include <ofono/plugin.h>
  #include <ofono/types.h>
+#include <ofono/modem.h>
 
  #include "ubloxmodem.h"
 
  static int ubloxmodem_init(void)
  {
  	ublox_gprs_context_init();
+	ublox_lte_init();
 
  	return 0;
  }
@@ -42,6 +44,7 @@ static int ubloxmodem_init(void)
  static void ubloxmodem_exit(void)
  {
  	ublox_gprs_context_exit();
+	ublox_lte_exit();
  }
 
  OFONO_PLUGIN_DEFINE(ubloxmodem, "U-Blox Toby L2 high speed modem driver",
drivers/ubloxmodem/ubloxmodem.h +0 -0
index 0c8a621..cf66412 100644

drivers/ubloxmodem/ubloxmodem.h line 30

Quoted 10 lines
drivers/ubloxmodem/ubloxmodem.h +5 -0
@@ -21,5 +21,10 @@
 
  #include <drivers/atmodem/atutil.h>
 
+#define UBLOXMODEM "ubloxmodem"
+
  extern void ublox_gprs_context_init(void);
  extern void ublox_gprs_context_exit(void);
+
+extern void ublox_lte_init(void);
+extern void ublox_lte_exit(void);

Regards,
-Denis

#14 lore raw

PATCH v2 8/9 build: add support for ublox lte atom driver

In reply to Dragos Tatulea
---
 Makefile.am | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
Makefile.am +3 -1
index 9d22365..08c7395 100644
@@ -382,7 +382,9 @@ builtin_modules += ubloxmodem
 builtin_sources += drivers/atmodem/atutil.h \
 			drivers/ubloxmodem/ubloxmodem.h \
 			drivers/ubloxmodem/ubloxmodem.c \
-			drivers/ubloxmodem/gprs-context.c
+			drivers/ubloxmodem/gprs-context.c \
+			drivers/ubloxmodem/lte.c
+
 
 
 if PHONESIM
Signature · 1 line
2.7.4
#15 lore raw

PATCH v2 9/9 plugins: ublox: enable lte driver for tobyl2

In reply to Dragos Tatulea
---
 plugins/ublox.c | 3 +++
 1 file changed, 3 insertions(+)
plugins/ublox.c +3 -0
index 092ba64..6d77df8 100644
@@ -38,6 +38,7 @@
 #include <ofono/sim.h>
 #include <ofono/gprs.h>
 #include <ofono/gprs-context.h>
+#include <ofono/lte.h>
 
 #include <drivers/atmodem/atutil.h>
 #include <drivers/atmodem/vendor.h>
@@ -313,6 +314,8 @@ static void ublox_post_sim(struct ofono_modem *modem)
 
 		--ncontexts;
 	}
+
+	ofono_lte_create(modem, "ubloxmodem", data->aux);
 }
 
 static void ublox_post_online(struct ofono_modem *modem)
Signature · 1 line
2.7.4