From: Sjur =?unknown-8bit?q?Br=C3=A6ndeland?= <sjurbren@gmail.com>
To: ofono@ofono.org
Subject: [PATCHv2] plugin: Add ste modem initd integration
Date: Wed, 15 Dec 2010 22:49:26 +0100 [thread overview]
Message-ID: <1292449768-6060-1-git-send-email-sjurbren@gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 10978 bytes --]
From: Sjur Brændeland <sjur.brandeland@stericsson.com>
This patch introduces auto discovery of ST-Ericsson modems.
ST-Ericsson modems (M5XX, 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. Multiple modem
instances, and reset handling is supported.
---
Changes:
- Support for multiple STE modems.
- Better naming of STE modem instances, using received dbus path.
- CAIF Link layer to use for AT channels specified pr modem instance.
- Added support for reset.
Makefile.am | 5 +
configure.ac | 6 +
plugins/stemid.c | 310 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 321 insertions(+), 0 deletions(-)
create mode 100644 plugins/stemid.c
diff --git a/Makefile.am b/Makefile.am
index 12b3c33..98096ae 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -82,6 +82,11 @@ gatchat_sources = gatchat/gatchat.h gatchat/gatchat.c \
udev_files = plugins/ofono.rules
+if STE_MODEM_INITD
+builtin_modules += stemid
+builtin_sources += plugins/stemid.c
+endif
+
if UDEV
builtin_modules += udev
builtin_sources += plugins/udev.c
diff --git a/configure.ac b/configure.ac
index 5c18f68..f733fc4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -177,6 +177,12 @@ AC_ARG_ENABLE(datafiles, AC_HELP_STRING([--disable-datafiles],
AM_CONDITIONAL(DATAFILES, test "${enable_datafiles}" != "no")
+AC_ARG_ENABLE(ste_modem_initd, AC_HELP_STRING([--disable-ste-modem-initd],
+ [disable auto discovery of STE modem using modem init daemon]),
+ [enable_ste_modem_initd=${enableval}])
+
+AM_CONDITIONAL(STE_MODEM_INITD, test "${enable_ste_modem_initd}" != "no")
+
if (test "${prefix}" = "NONE"); then
dnl no prefix and no localstatedir, so default to /var
if (test "$localstatedir" = '${prefix}/var'); then
diff --git a/plugins/stemid.c b/plugins/stemid.c
new file mode 100644
index 0000000..9f5da22
--- /dev/null
+++ b/plugins/stemid.c
@@ -0,0 +1,310 @@
+/*
+ *
+ * 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>
+
+#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 MID_SERVICE "com.stericsson.modeminit"
+#define MID_INTERFACE MID_SERVICE ".Modem"
+
+/* The signal StateChange sends the modem state.*/
+#define STATUS_CHANGED "StateChange"
+
+#define MID_ACTION_ON "on" /* Modem is on */
+#define MID_ACTION_RESET "dumping" /* Modem is resetting */
+#define MID_ACTION_UNKNOWN "unknown" /* Don't care */
+
+/* ResetState requests resending of StateChange. */
+#define MID_RESEND_STATE "ResendState"
+
+/* GetCaifIfName requests the CAIF Interface Name. */
+#define MID_GET_CAIFIF "GetCaifIfName"
+
+#define TIMEOUT 5000
+#define STE_DRIVER_NAME "ste"
+#define STE_INTERFACE_PROPERTY "Interface"
+
+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 mid_api_watch;
+static guint mid_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",
+ MID_GET_CAIFIF);
+ goto error;
+ }
+
+ if (strlen(ifname) > IF_NAMESIZE) {
+ ofono_error("STE Modem Init Daemon: %s bad response %s\n",
+ MID_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, STE_INTERFACE_PROPERTY,
+ 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(MID_SERVICE, path,
+ MID_INTERFACE, MID_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_DRIVER_NAME);
+ 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, MID_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, MID_ACTION_RESET) == 0) {
+ DBG("reset ongoing %s", path);
+ /* NOTE: Should we set powered = FALSE here? */
+ stemodem->state = STE_RESETTING;
+ } else if (g_strcmp0(action, MID_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, MID_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, MID_ACTION_RESET) != 0) {
+ DBG("STE modem unregistering %s %s", path, action);
+ g_hash_table_remove(modem_list, path);
+ }
+
+ break;
+ }
+}
+
+static gboolean mid_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 mid_connect(DBusConnection *connection, void *user_data)
+{
+ DBusMessage *message;
+
+ mid_state_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+ MID_INTERFACE,
+ STATUS_CHANGED,
+ mid_signal_status_change,
+ NULL, NULL);
+
+ message = dbus_message_new_method_call(MID_SERVICE, "/",
+ MID_INTERFACE, MID_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 mid_disconnect(DBusConnection *connection, void *user_data)
+{
+ g_hash_table_remove_all(modem_list);
+ g_dbus_remove_watch(connection, mid_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 stemid_init()
+{
+ connection = ofono_dbus_get_connection();
+ if (connection == NULL)
+ return -EIO;
+
+ modem_list = g_hash_table_new_full(g_str_hash, g_str_equal,
+ NULL, destroy_stemodem);
+ mid_api_watch = g_dbus_add_service_watch(connection, MID_SERVICE,
+ mid_connect, mid_disconnect, NULL, NULL);
+ return 0;
+}
+
+static void stemid_exit()
+{
+ DBusConnection *connection = ofono_dbus_get_connection();
+
+ g_hash_table_destroy(modem_list);
+ g_dbus_remove_watch(connection, mid_api_watch);
+}
+
+OFONO_PLUGIN_DEFINE(stemid, "STE Modem Init Daemon dbus api", VERSION,
+ OFONO_PLUGIN_PRIORITY_DEFAULT, stemid_init, stemid_exit)
--
1.7.0.4
next reply other threads:[~2010-12-15 21:49 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-12-15 21:49 Sjur =?unknown-8bit?q?Br=C3=A6ndeland?= [this message]
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 ` [PATCHv3] " Sjur =?unknown-8bit?q?Br=C3=A6ndeland?=
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=1292449768-6060-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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.