Open Source Telephony
 help / color / mirror / Atom feed
From: Sjur =?unknown-8bit?q?Br=C3=A6ndeland?= <sjurbren@gmail.com>
To: ofono@ofono.org
Subject: [PATCHv3] plugin: Add ste modem initd integration
Date: Tue, 21 Dec 2010 23:54:56 +0100	[thread overview]
Message-ID: <1292972096-7942-1-git-send-email-sjurbren@gmail.com> (raw)
In-Reply-To: <1292942189.2658.44.camel@aeonflux>

[-- Attachment #1: Type: text/plain, Size: 10698 bytes --]

From: Sjur Brændeland <sjur.brandeland@stericsson.com>

This patch introduces auto discovery of ST-Ericsson modems.
ST-Ericsson modems (M57XX, M7XX, M74XX) are managed by a
Modem Init Daemon responsible for start, power cycles,
flashing etc. This STE plugin monitors the modem state exposed
from the Modem Init Damon's Dbus API. When the modem is in state
"on" the STE modem is created and registered. Muliple modem
instances, and reset handling is supported.
---
Hi Marcel.

I think I have resolved most of your comments on my last patch set,
including the massive confusion caused by calling this MID ;-)

The only remark left is "ResendState". I have done this as simple as 
possible where you just re-send all state information for all modem
instances and implicit get the object-path (serial-id) for each modem
when the StateChange signal is received.

I really don't think resending the state information should be of much
concern as this only happens once - when oFono starts. The extra cost
of waking the other two STE daemons should be negligible, as they most
likely are initializing and preparing for communicating with the STE-modem
anyway.

Regards,
Sjur

 Makefile.am      |    3 +
 plugins/stemgr.c |  310 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 313 insertions(+), 0 deletions(-)
 create mode 100644 plugins/stemgr.c

diff --git a/Makefile.am b/Makefile.am
index 12b3c33..d9c0505 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -221,6 +221,9 @@ builtin_sources += drivers/atmodem/atutil.h \
 			drivers/ifxmodem/gprs-context.c \
 			drivers/ifxmodem/stk.c
 
+builtin_modules += stemgr
+builtin_sources += plugins/stemgr.c
+
 builtin_modules += stemodem
 builtin_sources += drivers/atmodem/atutil.h \
 			drivers/stemodem/stemodem.h \
diff --git a/plugins/stemgr.c b/plugins/stemgr.c
new file mode 100644
index 0000000..6317516
--- /dev/null
+++ b/plugins/stemgr.c
@@ -0,0 +1,309 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2010 ST-Ericsson AB.
+ *
+ *  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 <errno.h>
+#include <string.h>
+#include <net/if.h>
+
+#include <glib.h>
+#include <gdbus.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/dbus.h>
+
+/*
+ * ST-Ericsson's Modem Init Daemon is used for controling the modem power
+ * cycles and provides a dbus API for modem state and properties.
+ */
+#define MGR_SERVICE		"com.stericsson.modeminit"
+#define MGR_INTERFACE		MGR_SERVICE ".Modem"
+
+/* The signal StateChange sends the modem state.*/
+#define STATUS_CHANGED		"StateChange"
+
+#define MGR_ACTION_ON		"on"		/* Modem is on */
+#define MGR_ACTION_RESET	"dumping"	/* Modem is resetting */
+
+/*
+ * ResendState requests resending of StateChange. This method is only
+ * called at startup, in order to retrieve the modem's serial id,
+ * (object path) and state.
+ */
+#define MGR_RESEND_STATE	"ResendState"
+
+/* GetCaifIfName requests the CAIF Interface Name. */
+#define MGR_GET_CAIFIF		"GetCaifIfName"
+
+#define TIMEOUT		5000
+
+enum ste_state {
+	STE_PENDING,    /* Waiting for caifif and "on" notification */
+	STE_PENDING_IF, /* Waiting for caifif, already got "on" */
+	STE_REGISTERED, /* Modem is registered */
+	STE_RESETTING   /* Modem is resetting */
+};
+
+struct ste_modem {
+	char *path;
+	struct ofono_modem *modem;
+	enum ste_state state;
+	gboolean got_caifif;
+	gboolean pending_call;
+};
+
+static GHashTable *modem_list;
+static guint mgr_api_watch;
+static guint mgr_state_watch;
+static DBusConnection *connection;
+
+static void get_caifif_reply(DBusPendingCall *call, void *user_data)
+{
+	DBusMessage *reply;
+	char *ifname;
+	struct ste_modem *stemodem = user_data;
+
+	stemodem->pending_call = FALSE;
+	stemodem->got_caifif = TRUE;
+	reply = dbus_pending_call_steal_reply(call);
+
+	if (dbus_message_is_error(reply, DBUS_ERROR_SERVICE_UNKNOWN)) {
+		ofono_error("STE Modem Init Daemon: unavailable");
+		goto error;
+	}
+
+	if (dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &ifname,
+					DBUS_TYPE_INVALID) == FALSE) {
+		ofono_error("STE Modem Init Daemon: bad signature for %s",
+				MGR_GET_CAIFIF);
+		goto error;
+	}
+
+	if (strlen(ifname) > IF_NAMESIZE) {
+		ofono_error("STE Modem Init Daemon: %s bad response %s\n",
+				MGR_GET_CAIFIF, ifname);
+		goto error;
+	}
+
+	if (ifname != NULL) {
+		DBG("STE Modem '%s' uses CAIF interface '%s'\n", stemodem->path,
+			ifname);
+		ofono_modem_set_string(stemodem->modem, "Interface",
+			ifname);
+	}
+
+error:
+	if (stemodem->state == STE_PENDING_IF) {
+		DBG("Register STE modem %s", stemodem->path);
+		ofono_modem_register(stemodem->modem);
+		stemodem->state = STE_REGISTERED;
+	}
+
+	dbus_message_unref(reply);
+}
+
+static void get_caif_interface(const char *path, struct ste_modem *stemodem)
+{
+	DBusMessage *message;
+	DBusPendingCall *call;
+
+	stemodem->pending_call = TRUE;
+	message = dbus_message_new_method_call(MGR_SERVICE, path,
+					MGR_INTERFACE, MGR_GET_CAIFIF);
+
+	if (!message) {
+		ofono_error("Unable to allocate new D-Bus message");
+		goto error;
+	}
+
+	dbus_message_set_auto_start(message, FALSE);
+
+	if (dbus_connection_send_with_reply(connection, message,
+						&call, TIMEOUT) == FALSE) {
+		ofono_error("Sending D-Bus message failed");
+		stemodem->got_caifif = TRUE;
+		goto error;
+	}
+
+	if (call == NULL) {
+		DBG("D-Bus connection not available");
+		stemodem->got_caifif = TRUE;
+		goto error;
+	}
+
+	dbus_pending_call_set_notify(call, get_caifif_reply, stemodem, NULL);
+	dbus_pending_call_unref(call);
+
+error:
+	dbus_message_unref(message);
+}
+
+static void handle_stemodem(const char *action, const char *path)
+{
+	struct ste_modem *stemodem = g_hash_table_lookup(modem_list, path);
+
+	if (stemodem == NULL) {
+		DBG("created STE modem %s", path);
+		stemodem = g_try_new0(struct ste_modem, 1);
+		if (stemodem == NULL)
+			return;
+
+		/* remove '/' from path to create a leagal modem name */
+		stemodem->modem = ofono_modem_create(path+1, "ste");
+		if (stemodem->modem == NULL) {
+			ofono_error("STE Modem Init: Bad path: '%s'\n", path);
+			g_free(stemodem);
+			return;
+		}
+
+		stemodem->path = g_strdup(path);
+		stemodem->state = STE_PENDING;
+		g_hash_table_insert(modem_list, stemodem->path, stemodem);
+	}
+
+	if (!stemodem->got_caifif) {
+		DBG("request caif interface %s", path);
+		get_caif_interface(path, stemodem);
+		stemodem->state = STE_PENDING;
+	}
+
+	switch (stemodem->state) {
+	case STE_PENDING:
+		if (g_strcmp0(action, MGR_ACTION_ON) != 0)
+			break;
+		if (stemodem->got_caifif) {
+			DBG("register STE modem %s", path);
+			ofono_modem_register(stemodem->modem);
+			stemodem->state = STE_REGISTERED;
+		} else
+			stemodem->state = STE_PENDING_IF;
+		break;
+	case STE_PENDING_IF:
+		break;
+	case STE_REGISTERED:
+		if (g_strcmp0(action, MGR_ACTION_RESET) == 0) {
+			DBG("reset ongoing %s", path);
+			/* NOTE: Should we set powered = FALSE here? */
+			stemodem->state = STE_RESETTING;
+		} else if (g_strcmp0(action, MGR_ACTION_ON) != 0) {
+			DBG("STE modem unregistering %s %s", path, action);
+			g_hash_table_remove(modem_list, path);
+		}
+
+		break;
+	case STE_RESETTING:
+		if (g_strcmp0(action, MGR_ACTION_ON) == 0) {
+			DBG("STE modem reset complete %s", path);
+			if (ofono_modem_get_powered(stemodem->modem))
+				ofono_modem_reset(stemodem->modem);
+		} else if (g_strcmp0(action, MGR_ACTION_RESET) != 0) {
+			DBG("STE modem unregistering %s %s", path, action);
+			g_hash_table_remove(modem_list, path);
+		}
+
+		break;
+	}
+}
+
+static gboolean mgr_signal_status_change(DBusConnection *connection,
+					DBusMessage *message, void *user_data)
+{
+	const char *state;
+	const char *path = dbus_message_get_path(message);
+
+	if (dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &state,
+					DBUS_TYPE_INVALID) == FALSE) {
+		ofono_error("STE Modem Init Daemon: invalid signal signature");
+		return FALSE;
+	}
+
+	if (g_strcmp0(path, "/") == 0)
+		return TRUE;
+
+	handle_stemodem(state, path);
+	return TRUE;
+}
+
+static void mgr_connect(DBusConnection *connection, void *user_data)
+{
+	DBusMessage *message;
+
+	mgr_state_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+						MGR_INTERFACE,
+						STATUS_CHANGED,
+						mgr_signal_status_change,
+						NULL, NULL);
+
+	message = dbus_message_new_method_call(MGR_SERVICE, "/",
+					MGR_INTERFACE, MGR_RESEND_STATE);
+	if (!message) {
+		ofono_error("Unable to allocate new D-Bus message");
+		goto error;
+	}
+
+	if (dbus_connection_send(connection, message, NULL) == FALSE)
+		ofono_error("Sending D-Bus message failed");
+
+error:
+	dbus_message_unref(message);
+}
+
+static void mgr_disconnect(DBusConnection *connection, void *user_data)
+{
+	g_hash_table_remove_all(modem_list);
+	g_dbus_remove_watch(connection, mgr_state_watch);
+}
+
+static void destroy_stemodem(gpointer data)
+{
+	struct ste_modem *stemodem = data;
+
+	ofono_modem_remove(stemodem->modem);
+	g_free(stemodem->path);
+	g_free(stemodem);
+}
+
+static int stemgr_init()
+{
+	connection = ofono_dbus_get_connection();
+
+	modem_list = g_hash_table_new_full(g_str_hash, g_str_equal,
+						NULL, destroy_stemodem);
+	mgr_api_watch = g_dbus_add_service_watch(connection, MGR_SERVICE,
+				mgr_connect, mgr_disconnect, NULL, NULL);
+	return 0;
+}
+
+static void stemgr_exit()
+{
+	g_hash_table_destroy(modem_list);
+	g_dbus_remove_watch(connection, mgr_api_watch);
+}
+
+OFONO_PLUGIN_DEFINE(stemgr, "oFono client of ST-Ericsson Modem Init Daemon",
+			VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT,
+			stemgr_init, stemgr_exit)
-- 
1.7.0.4


      parent reply	other threads:[~2010-12-21 22:54 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-12-15 21:49 [PATCHv2] plugin: Add ste modem initd integration Sjur =?unknown-8bit?q?Br=C3=A6ndeland?=
2010-12-15 21:49 ` [PATCHv2 1/2] stemodem: Create network interfaces statically Sjur =?unknown-8bit?q?Br=C3=A6ndeland?=
2010-12-21 14:38   ` Marcel Holtmann
2010-12-15 21:49 ` [PATCHv2 2/2] stemodem: Use RTNL to create network interfaces Sjur =?unknown-8bit?q?Br=C3=A6ndeland?=
2010-12-21 14:38   ` Marcel Holtmann
2010-12-21 14:36 ` [PATCHv2] plugin: Add ste modem initd integration Marcel Holtmann
2010-12-21 15:06   ` Sjur =?unknown-8bit?q?Br=C3=A6ndeland?=
2010-12-21 15:18     ` Marcel Holtmann
2010-12-21 15:37       ` Sjur =?unknown-8bit?q?Br=C3=A6ndeland?=
2010-12-23  2:48         ` Marcel Holtmann
2011-01-03 21:42           ` Sjur =?unknown-8bit?q?Br=C3=A6ndeland?=
2011-01-03 21:55             ` Marcel Holtmann
2011-01-03 22:30               ` Sjur =?unknown-8bit?q?Br=C3=A6ndeland?=
2011-01-03 22:54                 ` Marcel Holtmann
2011-01-03 23:12                   ` Sjur =?unknown-8bit?q?Br=C3=A6ndeland?=
2011-01-04  9:49                     ` Marcel Holtmann
2011-01-04 19:07                       ` [PATCHv4 0/1] STE Modem Init Daemon integration Sjur =?unknown-8bit?q?Br=C3=A6ndeland?=
2011-01-04 19:07                       ` [PATCHv4 1/1] plugin: Add ste modem initd integration Sjur =?unknown-8bit?q?Br=C3=A6ndeland?=
2011-01-05 22:06                         ` Marcel Holtmann
2011-01-06  9:38                           ` [PATCHv5] " Sjur =?unknown-8bit?q?Br=C3=A6ndeland?=
2011-01-11  0:58                             ` Marcel Holtmann
2011-01-11 17:06                               ` Sjur =?unknown-8bit?q?Br=C3=A6ndeland?=
2011-01-11 21:52                                 ` Marcel Holtmann
2011-01-11 21:56                                   ` Denis Kenzior
2011-01-11 22:05                                     ` Marcel Holtmann
2011-01-11 22:39                                     ` [PATCH] coding-style: Use void if function has no parameters Sjur =?unknown-8bit?q?Br=C3=A6ndeland?=
2011-01-11 22:48                                       ` Marcel Holtmann
2011-01-11 22:24                                   ` [PATCHv6] plugin: Add ste modem initd integration Sjur =?unknown-8bit?q?Br=C3=A6ndeland?=
2011-01-11 22:35                                     ` Marcel Holtmann
2011-01-11 22:41                                       ` Sjur =?unknown-8bit?q?Br=C3=A6ndeland?=
2011-01-11 22:56                                         ` [PATCHv7] " Sjur =?unknown-8bit?q?Br=C3=A6ndeland?=
2011-01-11 22:58                                           ` Marcel Holtmann
2010-12-21 22:54   ` Sjur =?unknown-8bit?q?Br=C3=A6ndeland?= [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1292972096-7942-1-git-send-email-sjurbren@gmail.com \
    --to=sjurbren@gmail.com \
    --cc=ofono@ofono.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox