All of lore.kernel.org
 help / color / mirror / Atom feed
* [n900 PATCH 0/5] n900 modem drivers
@ 2010-09-15 16:59 Pekka.Pessi
  2010-09-15 16:59 ` [n900 PATCH 1/5] Include isimodem sources always in dist Pekka.Pessi
  0 siblings, 1 reply; 13+ messages in thread
From: Pekka.Pessi @ 2010-09-15 16:59 UTC (permalink / raw)
  To: ofono

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

Hi all,

I did some restructuring on the isimodem side as proposed by Denis. Now
the driver/isimodem does not contain a modem driver, but it is in the
isigen plugin (á la atgen). The "isimodem" modem driver is removed.

The n900 modem driver seems to run on Nokia N900 with meego kernel and userspace.

The n900maemo plugin is for Nokia N900s running Maemo userspace.

--Pekka


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [n900 PATCH 1/5] Include isimodem sources always in dist
  2010-09-15 16:59 [n900 PATCH 0/5] n900 modem drivers Pekka.Pessi
@ 2010-09-15 16:59 ` Pekka.Pessi
  2010-09-15 16:59   ` [n900 PATCH 2/5] isigen: generic modem driver plugin for isimodems Pekka.Pessi
  0 siblings, 1 reply; 13+ messages in thread
From: Pekka.Pessi @ 2010-09-15 16:59 UTC (permalink / raw)
  To: ofono

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

From: Pekka Pessi <ppessi@hamsa.research.nokia.com>

---
 Makefile.am |   14 ++++++++++----
 1 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 802e94b..79ef4e4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -94,9 +94,7 @@ if DATAFILES
 conf_DATA += plugins/modem.conf
 endif
 
-if ISIMODEM
-builtin_modules += isimodem
-builtin_sources += $(gisi_sources) \
+isimodem_sources = $(gisi_sources) \
 				drivers/isimodem/isimodem.h \
 				drivers/isimodem/isimodem.c \
 				drivers/isimodem/mtc.h \
@@ -130,8 +128,14 @@ builtin_sources += $(gisi_sources) \
 				drivers/isimodem/gprs-context.c \
 				drivers/isimodem/gpds.h
 
+usbpn_sources = plugins/usbpnmodem.c
+
+if ISIMODEM
+builtin_modules += isimodem
+builtin_sources += $(isimodem_sources)
+
 builtin_modules += usbpnmodem
-builtin_sources += plugins/usbpnmodem.c
+builtin_sources += $(usbpn_sources)
 endif
 
 if ATMODEM
@@ -377,6 +381,8 @@ endif
 conf_files = src/ofono.conf plugins/modem.conf
 
 EXTRA_DIST = src/genbuiltin plugins/example_history.c $(doc_files) \
+				$(isimodem_sources) \
+				$(usbpn_sources) \
 				$(test_scripts) $(conf_files) $(udev_files)
 
 dist_man_MANS = doc/ofonod.8
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [n900 PATCH 2/5] isigen: generic modem driver plugin for isimodems
  2010-09-15 16:59 ` [n900 PATCH 1/5] Include isimodem sources always in dist Pekka.Pessi
@ 2010-09-15 16:59   ` Pekka.Pessi
  2010-09-15 16:59     ` [n900 PATCH 3/5] isimodem: remove the modem driver parts Pekka.Pessi
  2010-09-15 18:07     ` [n900 PATCH 2/5] isigen: generic modem driver plugin for isimodems =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
  0 siblings, 2 replies; 13+ messages in thread
From: Pekka.Pessi @ 2010-09-15 16:59 UTC (permalink / raw)
  To: ofono

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

From: Pekka Pessi <ppessi@hamsa.research.nokia.com>

The new isigen modem driver replaces the uspnmodem plugin and the
generic isimodem driver.
---
 Makefile.am          |    8 +-
 plugins/isigen.c     |  518 ++++++++++++++++++++++++++++++++++++++++++++++++++
 plugins/usbpnmodem.c |  104 ----------
 3 files changed, 522 insertions(+), 108 deletions(-)
 create mode 100644 plugins/isigen.c
 delete mode 100644 plugins/usbpnmodem.c

diff --git a/Makefile.am b/Makefile.am
index 79ef4e4..aca5d1b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -128,14 +128,14 @@ isimodem_sources = $(gisi_sources) \
 				drivers/isimodem/gprs-context.c \
 				drivers/isimodem/gpds.h
 
-usbpn_sources = plugins/usbpnmodem.c
+isigen_sources = plugins/isigen.c
 
 if ISIMODEM
 builtin_modules += isimodem
 builtin_sources += $(isimodem_sources)
 
-builtin_modules += usbpnmodem
-builtin_sources += $(usbpn_sources)
+builtin_modules += isigen
+builtin_sources += $(isigen_sources)
 endif
 
 if ATMODEM
@@ -382,7 +382,7 @@ conf_files = src/ofono.conf plugins/modem.conf
 
 EXTRA_DIST = src/genbuiltin plugins/example_history.c $(doc_files) \
 				$(isimodem_sources) \
-				$(usbpn_sources) \
+				$(isigen_sources) \
 				$(test_scripts) $(conf_files) $(udev_files)
 
 dist_man_MANS = doc/ofonod.8
diff --git a/plugins/isigen.c b/plugins/isigen.c
new file mode 100644
index 0000000..1439a49
--- /dev/null
+++ b/plugins/isigen.c
@@ -0,0 +1,518 @@
+/*
+ * This file is part of oFono - Open Source Telephony
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * 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 <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+
+#include <gisi/netlink.h>
+#include <gisi/client.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/devinfo.h>
+#include <ofono/phonebook.h>
+#include <ofono/netreg.h>
+#include <ofono/voicecall.h>
+#include <ofono/sms.h>
+#include <ofono/cbs.h>
+#include <ofono/sim.h>
+#include <ofono/ussd.h>
+#include <ofono/ssn.h>
+#include <ofono/call-forwarding.h>
+#include <ofono/call-settings.h>
+#include <ofono/call-barring.h>
+#include <ofono/call-meter.h>
+#include <ofono/radio-settings.h>
+#include <ofono/gprs.h>
+#include <ofono/gprs-context.h>
+
+#include "drivers/isimodem/isimodem.h"
+#include "drivers/isimodem/isiutil.h"
+#include "drivers/isimodem/mtc.h"
+#include "drivers/isimodem/debug.h"
+
+struct isi_data {
+	struct ofono_modem *modem;
+	char const *ifname;
+	GIsiModem *idx;
+	GIsiClient *client;
+	GPhonetNetlink *link;
+	GPhonetLinkState linkstate;
+	unsigned interval;
+	int reported;
+	ofono_bool_t online;
+	struct isi_cb_data *online_cbd;
+};
+
+static void report_powered(struct isi_data *isi, ofono_bool_t powered)
+{
+	if (powered != isi->reported)
+		ofono_modem_set_powered(isi->modem, isi->reported = powered);
+}
+
+static void report_online(struct isi_data *isi, ofono_bool_t online)
+{
+	struct isi_cb_data *cbd = isi->online_cbd;
+	ofono_modem_online_cb_t cb = cbd->cb;
+
+	isi->online_cbd = NULL;
+
+	if (isi->online == online)
+		CALLBACK_WITH_SUCCESS(cb, cbd->data);
+	else
+		CALLBACK_WITH_FAILURE(cb, cbd->data);
+
+	g_free(cbd);
+}
+
+static void set_power_by_mtc_state(struct isi_data *isi, int mtc_state)
+{
+	if (isi->online_cbd)
+		report_online(isi, mtc_state == MTC_NORMAL);
+
+	switch (mtc_state) {
+	case MTC_STATE_NONE:
+	case MTC_POWER_OFF:
+	case MTC_CHARGING:
+	case MTC_SELFTEST_FAIL:
+		report_powered(isi, 0);
+		break;
+
+	case MTC_RF_INACTIVE:
+	case MTC_NORMAL:
+	default:
+		report_powered(isi, 1);
+	}
+}
+
+static void mtc_state_ind_cb(GIsiClient *client,
+				const void *restrict data, size_t len,
+				uint16_t object, void *opaque)
+{
+	const unsigned char *msg = data;
+	struct isi_data *isi = opaque;
+
+	if (!msg) {
+		DBG("ISI client error: %d", g_isi_client_error(client));
+		return;
+	}
+
+	if (len < 3 || msg[0] != MTC_STATE_INFO_IND)
+		return;
+
+	if (msg[2] == MTC_START) {
+		DBG("target modem state: %s (0x%02X)",
+			mtc_modem_state_name(msg[1]), msg[1]);
+	} else if (msg[2] == MTC_READY) {
+		DBG("current modem state: %s (0x%02X)",
+			mtc_modem_state_name(msg[1]), msg[1]);
+		set_power_by_mtc_state(isi, msg[1]);
+	}
+}
+
+static gboolean mtc_poll_query_cb(GIsiClient *client,
+					const void *restrict data, size_t len,
+					uint16_t object, void *opaque)
+{
+	const unsigned char *msg = data;
+	struct isi_data *isi = opaque;
+
+	if (!msg) {
+		const unsigned char req[] = {
+			MTC_STATE_QUERY_REQ, 0x00, 0x00
+		};
+
+		if (isi->linkstate != PN_LINK_UP)
+			return TRUE;
+
+		isi->interval *= 2;
+		if (isi->interval >= 20)
+			isi->interval = 20;
+
+		g_isi_request_make(client, req, sizeof(req),
+					isi->interval,
+					mtc_poll_query_cb, opaque);
+
+		return TRUE;
+	}
+
+	if (len < 3 || msg[0] != MTC_STATE_QUERY_RESP)
+		return FALSE;
+
+	g_isi_subscribe(client, MTC_STATE_INFO_IND, mtc_state_ind_cb, opaque);
+
+	DBG("current modem state: %s (0x%02X)",
+		mtc_modem_state_name(msg[1]), msg[1]);
+	DBG("target modem state: %s (0x%02X)",
+		mtc_modem_state_name(msg[2]), msg[2]);
+
+	if (msg[1] == msg[2])
+		set_power_by_mtc_state(isi, msg[1]);
+
+	return TRUE;
+}
+
+static gboolean mtc_query_cb(GIsiClient *client,
+				const void *restrict data, size_t len,
+				uint16_t object, void *opaque)
+{
+	const unsigned char *msg = data;
+	struct isi_data *isi = opaque;
+
+	if (!msg) {
+		DBG("ISI client error: %d", g_isi_client_error(client));
+		return TRUE;
+	}
+
+	if (len < 3 || msg[0] != MTC_STATE_QUERY_RESP)
+		return FALSE;
+
+	DBG("current modem state: %s (0x%02X)",
+		mtc_modem_state_name(msg[1]), msg[1]);
+	DBG("target modem state: %s (0x%02X)",
+		mtc_modem_state_name(msg[2]), msg[2]);
+
+	if (msg[1] == msg[2])
+		set_power_by_mtc_state(isi, msg[1]);
+
+	return TRUE;
+}
+
+static void reachable_cb(GIsiClient *client, gboolean alive, uint16_t object,
+				void *opaque)
+{
+	struct isi_data *isi = opaque;
+
+	const unsigned char msg[] = {
+		MTC_STATE_QUERY_REQ,
+		0x00, 0x00 /* Filler */
+	};
+
+	if (!alive) {
+		DBG("MTC client: %s", strerror(-g_isi_client_error(client)));
+
+		if (isi->linkstate == PN_LINK_UP)
+			g_isi_request_make(client, msg, sizeof(msg),
+						isi->interval = MTC_TIMEOUT,
+						mtc_poll_query_cb, opaque);
+		return;
+	}
+
+	DBG("%s (v.%03d.%03d) reachable",
+		pn_resource_name(g_isi_client_resource(client)),
+		g_isi_version_major(client),
+		g_isi_version_minor(client));
+
+	g_isi_subscribe(client, MTC_STATE_INFO_IND, mtc_state_ind_cb, opaque);
+	g_isi_request_make(client, msg, sizeof(msg), MTC_TIMEOUT,
+				mtc_query_cb, opaque);
+}
+
+static void phonet_status_cb(GIsiModem *idx,
+				GPhonetLinkState st,
+				char const *ifname,
+				void *data)
+{
+	struct ofono_modem *modem = data;
+	struct isi_data *isi = ofono_modem_get_data(modem);
+
+	DBG("Link %s (%u) is %s",
+		isi->ifname, g_isi_modem_index(isi->idx),
+		st == PN_LINK_REMOVED ? "removed" :
+		st == PN_LINK_DOWN ? "down" : "up");
+
+	isi->linkstate = st;
+
+	if (st == PN_LINK_UP)
+		g_isi_verify(isi->client, reachable_cb, isi);
+	else if (st == PN_LINK_DOWN)
+		set_power_by_mtc_state(isi, MTC_STATE_NONE);
+	else if (st == PN_LINK_REMOVED)
+		ofono_modem_remove(modem);
+}
+
+static int isigen_probe(struct ofono_modem *modem)
+{
+	struct isi_data *isi;
+	char const *ifname = ofono_modem_get_string(modem, "Interface");
+	GIsiModem *idx;
+	GPhonetNetlink *link;
+
+	if (ifname == NULL)
+		return -EINVAL;
+
+	DBG("(%p) with %s", modem, ifname);
+
+	idx = g_isi_modem_by_name(ifname);
+	if (idx == NULL) {
+		DBG("Interface=%s: %s", ifname, strerror(errno));
+		return -errno;
+	}
+
+	if (g_pn_netlink_by_modem(idx)) {
+		DBG("%s: %s", ifname, strerror(EBUSY));
+		return -EBUSY;
+	}
+
+	link = g_pn_netlink_start(idx, phonet_status_cb, modem);
+	if (!link) {
+		DBG("%s: %s", ifname, strerror(errno));
+		return -errno;
+	}
+
+	isi = g_new0(struct isi_data, 1);
+	if (isi == NULL)
+		return -ENOMEM;
+
+	ofono_modem_set_data(isi->modem = modem, isi);
+
+	isi->idx = idx;
+	isi->ifname = ifname;
+	isi->link = link;
+	isi->client = g_isi_client_create(isi->idx, PN_MTC);
+	isi->reported = -1;
+
+	return 0;
+}
+
+static void isigen_remove(struct ofono_modem *modem)
+{
+	struct isi_data *isi = ofono_modem_get_data(modem);
+
+	if (!isi)
+		return;
+
+	ofono_modem_set_data(modem, NULL);
+	g_isi_client_destroy(isi->client);
+	g_pn_netlink_stop(isi->link);
+	g_free(isi);
+}
+
+static gboolean mtc_state_cb(GIsiClient *client,
+				const void *restrict data, size_t len,
+				uint16_t object, void *opaque)
+{
+	struct isi_cb_data *cbd = opaque;
+	struct ofono_modem *modem = cbd->user;
+	ofono_modem_online_cb_t cb = cbd->cb;
+	struct isi_data *isi = ofono_modem_get_data(modem);
+	const unsigned char *msg = data;
+
+	if (!msg) {
+		DBG("ISI client error: %d", g_isi_client_error(client));
+		goto err;
+	}
+
+	if (len < 3 || msg[0] != MTC_STATE_RESP)
+		return FALSE;
+
+	DBG("cause: %s (0x%02X)", mtc_isi_cause_name(msg[1]), msg[1]);
+
+	if (msg[1] == MTC_OK) {
+		isi->online_cbd = cbd;
+		return TRUE;
+	}
+
+err:
+	if (msg && msg[1] == MTC_ALREADY_ACTIVE)
+		CALLBACK_WITH_SUCCESS(cb, cbd->data);
+	else
+		CALLBACK_WITH_FAILURE(cb, cbd->data);
+
+	g_free(cbd);
+	return TRUE;
+}
+
+static void isigen_online(struct ofono_modem *modem, ofono_bool_t online,
+				ofono_modem_online_cb_t cb, void *data)
+{
+	struct isi_data *isi = ofono_modem_get_data(modem);
+	const unsigned char req[] = {
+		MTC_STATE_REQ, online ? MTC_NORMAL : MTC_RF_INACTIVE, 0x00
+	};
+	struct isi_cb_data *cbd = isi_cb_data_new(modem, cb, data);
+
+	DBG("(%p) with %s", modem, isi->ifname);
+
+	if (!cbd)
+		goto error;
+
+	isi->online = online;
+
+	if (g_isi_request_make(isi->client, req, sizeof(req), MTC_TIMEOUT,
+				mtc_state_cb, cbd))
+		return;
+
+error:
+	g_free(cbd);
+	CALLBACK_WITH_FAILURE(cb, data);
+}
+
+static void isigen_pre_sim(struct ofono_modem *modem)
+{
+	struct isi_data *isi = ofono_modem_get_data(modem);
+
+	DBG("(%p) with %s", modem, isi->ifname);
+
+	ofono_sim_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_devinfo_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_voicecall_create(isi->modem, 0, "isimodem", isi->idx);
+}
+
+static void isigen_post_sim(struct ofono_modem *modem)
+{
+	struct isi_data *isi = ofono_modem_get_data(modem);
+
+	DBG("(%p) with %s", modem, isi->ifname);
+
+	ofono_phonebook_create(isi->modem, 0, "isimodem", isi->idx);
+}
+
+static void isigen_post_online(struct ofono_modem *modem)
+{
+	struct isi_data *isi = ofono_modem_get_data(modem);
+	struct ofono_gprs *gprs;
+	struct ofono_gprs_context *gc;
+
+	DBG("(%p) with %s", modem, isi->ifname);
+
+	ofono_netreg_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_sms_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_cbs_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_ssn_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_ussd_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_call_forwarding_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_call_settings_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_call_barring_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_call_meter_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_radio_settings_create(isi->modem, 0, "isimodem", isi->idx);
+	gprs = ofono_gprs_create(isi->modem, 0, "isimodem", isi->idx);
+	gc = ofono_gprs_context_create(isi->modem, 0, "isimodem", isi->idx);
+
+	if (gprs && gc)
+		ofono_gprs_add_context(gprs, gc);
+	else
+		DBG("Failed to add context");
+}
+
+static int match_ifname(char const *name, char const *ifname)
+{
+	size_t namelen = strlen(name);
+
+	if (strncmp(name, ifname, namelen) != 0)
+		return FALSE;
+
+	if (ifname[namelen + strspn(ifname + namelen, "0123456789")] != '\0')
+		return FALSE;
+
+	return TRUE;
+}
+
+static struct ofono_modem_driver driver = {
+	.name = "isigen",
+	.probe = isigen_probe,
+	.remove = isigen_remove,
+	.set_online = isigen_online,
+	.pre_sim = isigen_pre_sim,
+	.post_sim = isigen_post_sim,
+	.post_online = isigen_post_online,
+};
+
+/*
+ * Add/remove isigen modem when usbpn* phonet interfaces are
+ * added/removed
+ */
+static void usbpn_status_cb(GIsiModem *idx,
+				GPhonetLinkState st,
+				char const ifname[],
+				void *data)
+{
+	struct ofono_modem *modem;
+	int error;
+	uint8_t address = 0;
+
+	DBG("Phonet link %s (%u) is %s",
+		ifname, g_isi_modem_index(idx),
+		st == PN_LINK_REMOVED ? "removed" :
+		st == PN_LINK_DOWN ? "down" : "up");
+
+	if (st == PN_LINK_REMOVED)
+		return;
+
+	if (!match_ifname("usbpn", ifname))
+		return;
+
+	address = PN_DEV_PC;
+
+	if (g_pn_netlink_by_modem(idx)) {
+		DBG("Modem for interface %s already exists", ifname);
+		return;
+	}
+
+	error = g_pn_netlink_set_address(idx, address);
+	if (error && error != -EEXIST) {
+		DBG("g_pn_netlink_set_address: %s\n", strerror(-error));
+		return;
+	}
+
+	modem = ofono_modem_create(NULL, "isimodem");
+	if (!modem)
+		return;
+
+	ofono_modem_set_string(modem, "Interface", ifname);
+
+	if (ofono_modem_register(modem) == 0)
+		DBG("Done regging modem %s", ofono_modem_get_path(modem));
+	else
+		ofono_modem_remove(modem);
+}
+
+static GPhonetNetlink *usbpn_link;
+
+static int isigen_init(void)
+{
+	ofono_modem_driver_register(&driver);
+
+	usbpn_link = g_pn_netlink_start(NULL, usbpn_status_cb, NULL);
+
+	return 0;
+}
+
+static void isigen_exit(void)
+{
+	g_pn_netlink_stop(usbpn_link);
+	usbpn_link = NULL;
+
+	ofono_modem_driver_unregister(&driver);
+}
+
+OFONO_PLUGIN_DEFINE(isigen, "Hotplug driver for isimodem", VERSION,
+			OFONO_PLUGIN_PRIORITY_DEFAULT,
+			isigen_init, isigen_exit)
diff --git a/plugins/usbpnmodem.c b/plugins/usbpnmodem.c
deleted file mode 100644
index 68beb6f..0000000
--- a/plugins/usbpnmodem.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * This file is part of oFono - Open Source Telephony
- *
- * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
- *
- * 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 <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-
-#include <gisi/netlink.h>
-#include <gisi/client.h>
-
-#define OFONO_API_SUBJECT_TO_CHANGE
-#include <ofono/plugin.h>
-#include <ofono/log.h>
-#include <ofono/modem.h>
-
-static GPhonetNetlink *link = NULL;
-
-/*
- * Add or remove isimodems
- * when usbpn* phonet interfaces are added/removed
- */
-static void usbpn_status_cb(GIsiModem *idx,
-				GPhonetLinkState st,
-				char const ifname[],
-				void *data)
-{
-	struct ofono_modem *modem;
-	int error;
-
-	DBG("Phonet link %s (%u) is %s",
-		ifname, g_isi_modem_index(idx),
-		st == PN_LINK_REMOVED ? "removed" :
-		st == PN_LINK_DOWN ? "down" : "up");
-
-	/* Expect phonet interface name usbpn<idx> */
-	if (strncmp(ifname, "usbpn", 5) ||
-		ifname[5 + strspn(ifname + 5, "0123456789")])
-		return;
-
-	if (st == PN_LINK_REMOVED)
-		return;
-
-	if (g_pn_netlink_by_modem(idx)) {
-		DBG("Modem for interface %s already exists", ifname);
-		return;
-	}
-
-	error = g_pn_netlink_set_address(idx, PN_DEV_PC);
-	if (error && error != -EEXIST) {
-		DBG("g_pn_netlink_set_address: %s\n", strerror(-error));
-		return;
-	}
-
-	modem = ofono_modem_create(NULL, "isimodem");
-	if (!modem)
-		return;
-
-	ofono_modem_set_string(modem, "Interface", ifname);
-
-	if (ofono_modem_register(modem) == 0)
-		DBG("Done regging modem %s", ofono_modem_get_path(modem));
-	else
-		ofono_modem_remove(modem);
-}
-
-static int usbpn_init(void)
-{
-	link = g_pn_netlink_start(NULL, usbpn_status_cb, NULL);
-	return 0;
-}
-
-static void usbpn_exit(void)
-{
-	g_pn_netlink_stop(link);
-	link = NULL;
-}
-
-OFONO_PLUGIN_DEFINE(usbpnmodem, "Hotplug driver for USB Phonet modems", VERSION,
-			OFONO_PLUGIN_PRIORITY_DEFAULT,
-			usbpn_init, usbpn_exit)
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [n900 PATCH 3/5] isimodem: remove the modem driver parts
  2010-09-15 16:59   ` [n900 PATCH 2/5] isigen: generic modem driver plugin for isimodems Pekka.Pessi
@ 2010-09-15 16:59     ` Pekka.Pessi
  2010-09-15 16:59       ` [n900 PATCH 4/5] n900: modem driver plugin for Nokia N900 Pekka.Pessi
  2010-09-15 18:07     ` [n900 PATCH 2/5] isigen: generic modem driver plugin for isimodems =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
  1 sibling, 1 reply; 13+ messages in thread
From: Pekka.Pessi @ 2010-09-15 16:59 UTC (permalink / raw)
  To: ofono

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

From: Pekka Pessi <ppessi@hamsa.research.nokia.com>

The isimodem driver is now part of isigen (just like atmodem and atgen).
---
 drivers/isimodem/isimodem.c |  401 -------------------------------------------
 1 files changed, 0 insertions(+), 401 deletions(-)

diff --git a/drivers/isimodem/isimodem.c b/drivers/isimodem/isimodem.c
index e7cac50..10d681e 100644
--- a/drivers/isimodem/isimodem.c
+++ b/drivers/isimodem/isimodem.c
@@ -29,408 +29,11 @@
 #include <string.h>
 #include <glib.h>
 
-#include <gisi/netlink.h>
-#include <gisi/client.h>
-
 #define OFONO_API_SUBJECT_TO_CHANGE
 #include <ofono/plugin.h>
 #include <ofono/log.h>
-#include <ofono/modem.h>
-#include <ofono/devinfo.h>
-#include <ofono/phonebook.h>
-#include <ofono/netreg.h>
-#include <ofono/voicecall.h>
-#include <ofono/sms.h>
-#include <ofono/cbs.h>
-#include <ofono/sim.h>
-#include <ofono/ussd.h>
-#include <ofono/ssn.h>
-#include <ofono/call-forwarding.h>
-#include <ofono/call-settings.h>
-#include <ofono/call-barring.h>
-#include <ofono/call-meter.h>
-#include <ofono/radio-settings.h>
-#include <ofono/gprs.h>
-#include <ofono/gprs-context.h>
 
 #include "isimodem.h"
-#include "isiutil.h"
-#include "mtc.h"
-#include "debug.h"
-
-struct isi_data {
-	struct ofono_modem *modem;
-	char const *ifname;
-	GIsiModem *idx;
-	GIsiClient *client;
-	GPhonetNetlink *link;
-	GPhonetLinkState linkstate;
-	unsigned interval;
-	int reported;
-	ofono_bool_t online;
-	struct isi_cb_data *online_cbd;
-};
-
-static void report_powered(struct isi_data *isi, ofono_bool_t powered)
-{
-	if (powered != isi->reported)
-		ofono_modem_set_powered(isi->modem, isi->reported = powered);
-}
-
-static void report_online(struct isi_data *isi, ofono_bool_t online)
-{
-	struct isi_cb_data *cbd = isi->online_cbd;
-	ofono_modem_online_cb_t cb = cbd->cb;
-
-	isi->online_cbd = NULL;
-
-	if (isi->online == online)
-		CALLBACK_WITH_SUCCESS(cb, cbd->data);
-	else
-		CALLBACK_WITH_FAILURE(cb, cbd->data);
-
-	g_free(cbd);
-}
-
-static void set_power_by_mtc_state(struct isi_data *isi, int mtc_state)
-{
-	if (isi->online_cbd)
-		report_online(isi, mtc_state == MTC_NORMAL);
-
-	switch (mtc_state) {
-	case MTC_STATE_NONE:
-	case MTC_POWER_OFF:
-	case MTC_CHARGING:
-	case MTC_SELFTEST_FAIL:
-		report_powered(isi, 0);
-		break;
-
-	case MTC_RF_INACTIVE:
-	case MTC_NORMAL:
-	default:
-		report_powered(isi, 1);
-	}
-}
-
-static void mtc_state_ind_cb(GIsiClient *client,
-				const void *restrict data, size_t len,
-				uint16_t object, void *opaque)
-{
-	const unsigned char *msg = data;
-	struct isi_data *isi = opaque;
-
-	if (!msg) {
-		DBG("ISI client error: %d", g_isi_client_error(client));
-		return;
-	}
-
-	if (len < 3 || msg[0] != MTC_STATE_INFO_IND)
-		return;
-
-	if (msg[2] == MTC_START) {
-		DBG("target modem state: %s (0x%02X)",
-			mtc_modem_state_name(msg[1]), msg[1]);
-	} else if (msg[2] == MTC_READY) {
-		DBG("current modem state: %s (0x%02X)",
-			mtc_modem_state_name(msg[1]), msg[1]);
-		set_power_by_mtc_state(isi, msg[1]);
-	}
-}
-
-static gboolean mtc_poll_query_cb(GIsiClient *client,
-					const void *restrict data, size_t len,
-					uint16_t object, void *opaque)
-{
-	const unsigned char *msg = data;
-	struct isi_data *isi = opaque;
-
-	if (!msg) {
-		const unsigned char req[] = {
-			MTC_STATE_QUERY_REQ, 0x00, 0x00
-		};
-
-		if (isi->linkstate != PN_LINK_UP)
-			return TRUE;
-
-		isi->interval *= 2;
-		if (isi->interval >= 20)
-			isi->interval = 20;
-
-		g_isi_request_make(client, req, sizeof(req),
-					isi->interval,
-					mtc_poll_query_cb, opaque);
-
-		return TRUE;
-	}
-
-	if (len < 3 || msg[0] != MTC_STATE_QUERY_RESP)
-		return FALSE;
-
-	g_isi_subscribe(client, MTC_STATE_INFO_IND, mtc_state_ind_cb, opaque);
-
-	DBG("current modem state: %s (0x%02X)",
-		mtc_modem_state_name(msg[1]), msg[1]);
-	DBG("target modem state: %s (0x%02X)",
-		mtc_modem_state_name(msg[2]), msg[2]);
-
-	if (msg[1] == msg[2])
-		set_power_by_mtc_state(isi, msg[1]);
-
-	return TRUE;
-}
-
-static gboolean mtc_query_cb(GIsiClient *client,
-				const void *restrict data, size_t len,
-				uint16_t object, void *opaque)
-{
-	const unsigned char *msg = data;
-	struct isi_data *isi = opaque;
-
-	if (!msg) {
-		DBG("ISI client error: %d", g_isi_client_error(client));
-		return TRUE;
-	}
-
-	if (len < 3 || msg[0] != MTC_STATE_QUERY_RESP)
-		return FALSE;
-
-	DBG("current modem state: %s (0x%02X)",
-		mtc_modem_state_name(msg[1]), msg[1]);
-	DBG("target modem state: %s (0x%02X)",
-		mtc_modem_state_name(msg[2]), msg[2]);
-
-	if (msg[1] == msg[2])
-		set_power_by_mtc_state(isi, msg[1]);
-
-	return TRUE;
-}
-
-static void reachable_cb(GIsiClient *client, gboolean alive, uint16_t object,
-				void *opaque)
-{
-	struct isi_data *isi = opaque;
-
-	const unsigned char msg[] = {
-		MTC_STATE_QUERY_REQ,
-		0x00, 0x00 /* Filler */
-	};
-
-	if (!alive) {
-		DBG("MTC client: %s", strerror(-g_isi_client_error(client)));
-
-		if (isi->linkstate == PN_LINK_UP)
-			g_isi_request_make(client, msg, sizeof(msg),
-						isi->interval = MTC_TIMEOUT,
-						mtc_poll_query_cb, opaque);
-		return;
-	}
-
-	DBG("%s (v.%03d.%03d) reachable",
-		pn_resource_name(g_isi_client_resource(client)),
-		g_isi_version_major(client),
-		g_isi_version_minor(client));
-
-	g_isi_subscribe(client, MTC_STATE_INFO_IND, mtc_state_ind_cb, opaque);
-	g_isi_request_make(client, msg, sizeof(msg), MTC_TIMEOUT,
-				mtc_query_cb, opaque);
-}
-
-static void phonet_status_cb(GIsiModem *idx,
-				GPhonetLinkState st,
-				char const *ifname,
-				void *data)
-{
-	struct ofono_modem *modem = data;
-	struct isi_data *isi = ofono_modem_get_data(modem);
-
-	DBG("Link %s (%u) is %s",
-		isi->ifname, g_isi_modem_index(isi->idx),
-		st == PN_LINK_REMOVED ? "removed" :
-		st == PN_LINK_DOWN ? "down" : "up");
-
-	isi->linkstate = st;
-
-	if (st == PN_LINK_UP)
-		g_isi_verify(isi->client, reachable_cb, isi);
-	else if (st == PN_LINK_DOWN)
-		set_power_by_mtc_state(isi, MTC_STATE_NONE);
-	else if (st == PN_LINK_REMOVED)
-		ofono_modem_remove(modem);
-}
-
-static int isi_modem_probe(struct ofono_modem *modem)
-{
-	struct isi_data *isi;
-	char const *ifname = ofono_modem_get_string(modem, "Interface");
-	GIsiModem *idx;
-	GPhonetNetlink *link;
-
-	if (ifname == NULL)
-		return -EINVAL;
-
-	DBG("(%p) with %s", modem, ifname);
-
-	idx = g_isi_modem_by_name(ifname);
-	if (idx == NULL) {
-		DBG("Interface=%s: %s", ifname, strerror(errno));
-		return -errno;
-	}
-
-	if (g_pn_netlink_by_modem(idx)) {
-		DBG("%s: %s", ifname, strerror(EBUSY));
-		return -EBUSY;
-	}
-
-	link = g_pn_netlink_start(idx, phonet_status_cb, modem);
-	if (!link) {
-		DBG("%s: %s", ifname, strerror(errno));
-		return -errno;
-	}
-
-	isi = g_new0(struct isi_data, 1);
-	if (isi == NULL)
-		return -ENOMEM;
-
-	ofono_modem_set_data(isi->modem = modem, isi);
-
-	isi->idx = idx;
-	isi->ifname = ifname;
-	isi->link = link;
-	isi->client = g_isi_client_create(isi->idx, PN_MTC);
-	isi->reported = -1;
-
-	return 0;
-}
-
-static void isi_modem_remove(struct ofono_modem *modem)
-{
-	struct isi_data *isi = ofono_modem_get_data(modem);
-
-	if (!isi)
-		return;
-
-	ofono_modem_set_data(modem, NULL);
-	g_isi_client_destroy(isi->client);
-	g_pn_netlink_stop(isi->link);
-	g_free(isi);
-}
-
-static gboolean mtc_state_cb(GIsiClient *client,
-				const void *restrict data, size_t len,
-				uint16_t object, void *opaque)
-{
-	struct isi_cb_data *cbd = opaque;
-	struct ofono_modem *modem = cbd->user;
-	ofono_modem_online_cb_t cb = cbd->cb;
-	struct isi_data *isi = ofono_modem_get_data(modem);
-	const unsigned char *msg = data;
-
-	if (!msg) {
-		DBG("ISI client error: %d", g_isi_client_error(client));
-		goto err;
-	}
-
-	if (len < 3 || msg[0] != MTC_STATE_RESP)
-		return FALSE;
-
-	DBG("cause: %s (0x%02X)", mtc_isi_cause_name(msg[1]), msg[1]);
-
-	if (msg[1] == MTC_OK) {
-		isi->online_cbd = cbd;
-		return TRUE;
-	}
-
-err:
-	if (msg && msg[1] == MTC_ALREADY_ACTIVE)
-		CALLBACK_WITH_SUCCESS(cb, cbd->data);
-	else
-		CALLBACK_WITH_FAILURE(cb, cbd->data);
-
-	g_free(cbd);
-	return TRUE;
-}
-
-static void isi_modem_online(struct ofono_modem *modem, ofono_bool_t online,
-				ofono_modem_online_cb_t cb, void *data)
-{
-	struct isi_data *isi = ofono_modem_get_data(modem);
-	const unsigned char req[] = {
-		MTC_STATE_REQ, online ? MTC_NORMAL : MTC_RF_INACTIVE, 0x00
-	};
-	struct isi_cb_data *cbd = isi_cb_data_new(modem, cb, data);
-
-	DBG("(%p) with %s", modem, isi->ifname);
-
-	if (!cbd)
-		goto error;
-
-	isi->online = online;
-
-	if (g_isi_request_make(isi->client, req, sizeof(req), MTC_TIMEOUT,
-				mtc_state_cb, cbd))
-		return;
-
-error:
-	g_free(cbd);
-	CALLBACK_WITH_FAILURE(cb, data);
-}
-
-static void isi_modem_pre_sim(struct ofono_modem *modem)
-{
-	struct isi_data *isi = ofono_modem_get_data(modem);
-
-	DBG("(%p) with %s", modem, isi->ifname);
-
-	ofono_sim_create(isi->modem, 0, "isimodem", isi->idx);
-	ofono_devinfo_create(isi->modem, 0, "isimodem", isi->idx);
-	ofono_voicecall_create(isi->modem, 0, "isimodem", isi->idx);
-}
-
-static void isi_modem_post_sim(struct ofono_modem *modem)
-{
-	struct isi_data *isi = ofono_modem_get_data(modem);
-
-	DBG("(%p) with %s", modem, isi->ifname);
-
-	ofono_phonebook_create(isi->modem, 0, "isimodem", isi->idx);
-}
-
-static void isi_modem_post_online(struct ofono_modem *modem)
-{
-	struct isi_data *isi = ofono_modem_get_data(modem);
-	struct ofono_gprs *gprs;
-	struct ofono_gprs_context *gc;
-
-	DBG("(%p) with %s", modem, isi->ifname);
-
-	ofono_netreg_create(isi->modem, 0, "isimodem", isi->idx);
-	ofono_sms_create(isi->modem, 0, "isimodem", isi->idx);
-	ofono_cbs_create(isi->modem, 0, "isimodem", isi->idx);
-	ofono_ssn_create(isi->modem, 0, "isimodem", isi->idx);
-	ofono_ussd_create(isi->modem, 0, "isimodem", isi->idx);
-	ofono_call_forwarding_create(isi->modem, 0, "isimodem", isi->idx);
-	ofono_call_settings_create(isi->modem, 0, "isimodem", isi->idx);
-	ofono_call_barring_create(isi->modem, 0, "isimodem", isi->idx);
-	ofono_call_meter_create(isi->modem, 0, "isimodem", isi->idx);
-	ofono_radio_settings_create(isi->modem, 0, "isimodem", isi->idx);
-	gprs = ofono_gprs_create(isi->modem, 0, "isimodem", isi->idx);
-	gc = ofono_gprs_context_create(isi->modem, 0, "isimodem", isi->idx);
-
-	if (gprs && gc)
-		ofono_gprs_add_context(gprs, gc);
-	else
-		DBG("Failed to add context");
-}
-
-static struct ofono_modem_driver driver = {
-	.name = "isimodem",
-	.probe = isi_modem_probe,
-	.remove = isi_modem_remove,
-	.set_online = isi_modem_online,
-	.pre_sim = isi_modem_pre_sim,
-	.post_sim = isi_modem_post_sim,
-	.post_online = isi_modem_post_online,
-};
 
 static int isimodem_init(void)
 {
@@ -451,15 +54,11 @@ static int isimodem_init(void)
 	isi_gprs_init();
 	isi_gprs_context_init();
 
-	ofono_modem_driver_register(&driver);
-
 	return 0;
 }
 
 static void isimodem_exit(void)
 {
-	ofono_modem_driver_unregister(&driver);
-
 	isi_devinfo_exit();
 	isi_phonebook_exit();
 	isi_netreg_exit();
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [n900 PATCH 4/5] n900: modem driver plugin for Nokia N900
  2010-09-15 16:59     ` [n900 PATCH 3/5] isimodem: remove the modem driver parts Pekka.Pessi
@ 2010-09-15 16:59       ` Pekka.Pessi
  2010-09-15 16:59         ` [n900 PATCH 5/5] n900maemo: modem driver plugin for N900 with Maemo Pekka.Pessi
  0 siblings, 1 reply; 13+ messages in thread
From: Pekka.Pessi @ 2010-09-15 16:59 UTC (permalink / raw)
  To: ofono

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

From: Pekka Pessi <ppessi@hamsa.research.nokia.com>

The n900 plugin has modem driver based on isimodem, controlling the N900
internal modem using the appropriate GPIO lines. It runs natively on
N900 with Maemo or Meego kernel.

The plugin conflicts with Maemo userspace, however.
---
 Makefile.am        |    6 +
 plugins/n900.c     |  573 +++++++++++++++++++++++++++++++++++++
 plugins/n900gpio.c |  796 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 plugins/n900gpio.h |   54 ++++
 4 files changed, 1429 insertions(+), 0 deletions(-)
 create mode 100644 plugins/n900.c
 create mode 100644 plugins/n900gpio.c
 create mode 100644 plugins/n900gpio.h

diff --git a/Makefile.am b/Makefile.am
index aca5d1b..d643ca8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -130,12 +130,17 @@ isimodem_sources = $(gisi_sources) \
 
 isigen_sources = plugins/isigen.c
 
+n900_sources = plugins/n900.c plugins/n900gpio.h plugins/n900gpio.c
+
 if ISIMODEM
 builtin_modules += isimodem
 builtin_sources += $(isimodem_sources)
 
 builtin_modules += isigen
 builtin_sources += $(isigen_sources)
+
+builtin_modules += n900
+builtin_sources += $(n900_sources)
 endif
 
 if ATMODEM
@@ -383,6 +388,7 @@ conf_files = src/ofono.conf plugins/modem.conf
 EXTRA_DIST = src/genbuiltin plugins/example_history.c $(doc_files) \
 				$(isimodem_sources) \
 				$(isigen_sources) \
+				$(n900_sources) \
 				$(test_scripts) $(conf_files) $(udev_files)
 
 dist_man_MANS = doc/ofonod.8
diff --git a/plugins/n900.c b/plugins/n900.c
new file mode 100644
index 0000000..bd0e156
--- /dev/null
+++ b/plugins/n900.c
@@ -0,0 +1,573 @@
+/*
+ * This file is part of oFono - Open Source Telephony
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * 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 <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+
+#include <gisi/modem.h>
+#include <gisi/netlink.h>
+#include <gisi/client.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/devinfo.h>
+#include <ofono/phonebook.h>
+#include <ofono/netreg.h>
+#include <ofono/voicecall.h>
+#include <ofono/sms.h>
+#include <ofono/cbs.h>
+#include <ofono/sim.h>
+#include <ofono/ussd.h>
+#include <ofono/ssn.h>
+#include <ofono/call-forwarding.h>
+#include <ofono/call-settings.h>
+#include <ofono/call-barring.h>
+#include <ofono/call-meter.h>
+#include <ofono/radio-settings.h>
+#include <ofono/gprs.h>
+#include <ofono/gprs-context.h>
+
+#include "drivers/isimodem/isimodem.h"
+#include "drivers/isimodem/isiutil.h"
+#include "drivers/isimodem/infoserver.h"
+#include "drivers/isimodem/mtc.h"
+#include "drivers/isimodem/debug.h"
+
+#include "n900gpio.h"
+
+struct isi_data {
+	struct ofono_modem *modem;
+	char const *ifname;
+	GIsiModem *idx;
+	GIsiClient *client;
+	struct n900_gpio *gpio;
+	struct isi_infoserver *infoserver;
+	int reported;
+	enum n900_power_state power_state;
+	int mtc_state;
+	guint timeout;
+	ofono_bool_t online;
+	struct isi_cb_data *online_cbd;
+};
+
+static void set_power_by_mtc_state(struct isi_data *isi, int state);
+static void mtc_power_off(struct isi_data *isi);
+static gboolean mtc_power_off_poll(gpointer user);
+
+static void report_powered(struct isi_data *isi, ofono_bool_t powered)
+{
+	if (powered != isi->reported)
+		ofono_modem_set_powered(isi->modem, isi->reported = powered);
+}
+
+static void report_online(struct isi_data *isi, ofono_bool_t online)
+{
+	struct isi_cb_data *cbd = isi->online_cbd;
+	ofono_modem_online_cb_t cb = cbd->cb;
+
+	isi->online_cbd = NULL;
+
+	if (isi->online == online)
+		CALLBACK_WITH_SUCCESS(cb, cbd->data);
+	else
+		CALLBACK_WITH_FAILURE(cb, cbd->data);
+
+	g_free(cbd);
+}
+
+static void set_power_by_mtc_state(struct isi_data *isi, int mtc_state)
+{
+	isi->mtc_state = mtc_state;
+
+	if (isi->online_cbd)
+		report_online(isi, mtc_state == MTC_NORMAL);
+
+	switch (mtc_state) {
+	case MTC_STATE_NONE:
+	case MTC_POWER_OFF:
+	case MTC_CHARGING:
+	case MTC_SELFTEST_FAIL:
+		report_powered(isi, 0);
+		break;
+
+	case MTC_RF_INACTIVE:
+	case MTC_NORMAL:
+	default:
+		report_powered(isi, 1);
+	}
+}
+
+static void mtc_state_ind_cb(GIsiClient *client, const void *restrict data,
+				size_t len, uint16_t object, void *opaque)
+{
+	const unsigned char *msg = data;
+	struct isi_data *isi = opaque;
+
+	if (!msg) {
+		DBG("ISI client error: %d", g_isi_client_error(client));
+		return;
+	}
+
+	if (len < 3 || msg[0] != MTC_STATE_INFO_IND)
+		return;
+
+	if (msg[2] == MTC_START) {
+		DBG("target modem state: %s (0x%02X)",
+			mtc_modem_state_name(msg[1]), msg[1]);
+		if (msg[1] == MTC_POWER_OFF) {
+			isi->power_state = POWER_OFF_STARTED_STATE;
+			mtc_power_off_poll(isi);
+		}
+	} else if (msg[2] == MTC_READY) {
+		DBG("current modem state: %s (0x%02X)",
+			mtc_modem_state_name(msg[1]), msg[1]);
+		set_power_by_mtc_state(isi, msg[1]);
+	}
+}
+
+static gboolean mtc_startup_synq_cb(GIsiClient *client,
+					const void *restrict data, size_t len,
+					uint16_t object, void *opaque)
+{
+	const unsigned char *msg = data;
+
+	if (!msg) {
+		DBG("%s: %s", "MTC_STARTUP_SYNQ",
+			strerror(-g_isi_client_error(client)));
+		return TRUE;
+	}
+
+	if (len < 3 || msg[0] != MTC_STARTUP_SYNQ_RESP)
+		return FALSE;
+
+	return TRUE;
+}
+
+static gboolean mtc_state_query_cb(GIsiClient *client,
+					const void *restrict data, size_t len,
+					uint16_t object, void *opaque)
+{
+	const unsigned char *msg = data;
+	struct isi_data *isi = opaque;
+
+	if (!msg) {
+		DBG("ISI client error: %d", g_isi_client_error(client));
+		return TRUE;
+	}
+
+	if (len < 3 || msg[0] != MTC_STATE_QUERY_RESP)
+		return FALSE;
+
+	DBG("current modem state: %s (0x%02X)",
+		mtc_modem_state_name(msg[1]), msg[1]);
+	DBG("target modem state: %s (0x%02X)",
+		mtc_modem_state_name(msg[2]), msg[2]);
+
+	set_power_by_mtc_state(isi, msg[1]);
+
+	{
+		const unsigned char msg[3] = {
+			MTC_STARTUP_SYNQ_REQ,
+		};
+		g_isi_request_make(client, msg, sizeof(msg), MTC_TIMEOUT,
+					mtc_startup_synq_cb, opaque);
+	}
+
+	return TRUE;
+}
+
+static void reachable_cb(GIsiClient *client, gboolean alive, uint16_t object,
+				void *opaque)
+{
+	const unsigned char msg[] = {
+		MTC_STATE_QUERY_REQ,
+		0x00, 0x00 /* Filler */
+	};
+
+	if (!alive) {
+		DBG("MTC client: %s", strerror(-g_isi_client_error(client)));
+		/* XXX */
+		return;
+	}
+
+	DBG("%s (v.%03d.%03d) reachable",
+		pn_resource_name(g_isi_client_resource(client)),
+		g_isi_version_major(client),
+		g_isi_version_minor(client));
+
+	g_isi_subscribe(client, MTC_STATE_INFO_IND, mtc_state_ind_cb, opaque);
+	g_isi_request_make(client, msg, sizeof(msg), MTC_TIMEOUT,
+				mtc_state_query_cb, opaque);
+}
+
+static gboolean mtc_power_off_poll(gpointer user)
+{
+	struct isi_data *isi = user;
+
+	const unsigned char req[] = {
+		MTC_SHUTDOWN_SYNC_REQ,
+		0x00, 0x00 /* Filler */
+	};
+
+	isi->timeout = 0;
+
+	if (isi->power_state == POWER_ON_STARTED_STATE ||
+		isi->power_state == POWER_OFF_STATE ||
+		isi->power_state == POWER_OFF_WAITING_STATE)
+		return FALSE;
+
+	g_isi_request_make(isi->client, req, sizeof(req), MTC_TIMEOUT,
+				NULL, NULL);
+
+	isi->timeout = g_timeout_add(200, mtc_power_off_poll, user);
+
+	return FALSE;
+}
+
+static gboolean mtc_power_off_cb(GIsiClient *client,
+					const void *restrict data, size_t len,
+					uint16_t object, void *opaque)
+{
+	struct isi_data *isi = opaque;
+	const unsigned char *msg = data;
+
+	if (!msg) {
+		DBG("%s: %s", "MTC_POWER_OFF_RESP",
+			strerror(-g_isi_client_error(client)));
+		if (isi->power_state == POWER_OFF_STARTED_STATE)
+			mtc_power_off(isi);
+		return TRUE;
+	}
+
+	if (len < 3 || msg[0] != MTC_POWER_OFF_RESP)
+		return FALSE;
+
+	return TRUE;
+}
+
+static void mtc_power_off(struct isi_data *isi)
+{
+	const unsigned char req[] = {
+		MTC_POWER_OFF_REQ,
+		0x00, 0x00 /* Filler */
+	};
+
+	g_isi_request_make(isi->client, req, sizeof(req), MTC_TIMEOUT,
+				mtc_power_off_cb, isi);
+}
+
+static void n900_modem_power_cb(enum n900_power_state state,
+				void *data)
+{
+	struct ofono_modem *modem = data;
+	struct isi_data *isi = ofono_modem_get_data(modem);
+
+	DBG("power state %s", n900_power_state_name(state));
+
+	isi->power_state = state;
+
+	if (state == POWER_OFF_STARTED_STATE)
+		mtc_power_off(isi);
+	else if (isi->timeout)
+		g_source_remove(isi->timeout);
+
+	if (state == POWER_ON_STATE)
+		g_isi_verify(isi->client, reachable_cb, isi);
+	else
+		set_power_by_mtc_state(isi, MTC_STATE_NONE);
+}
+
+static int n900_modem_probe(struct ofono_modem *modem)
+{
+	char const *ifname = ofono_modem_get_string(modem, "Interface");
+	GIsiModem *idx;
+	struct isi_data *isi;
+
+	if (ifname == NULL)
+		ifname = "phonet0";
+
+	DBG("(%p) with %s", modem, ifname);
+
+	idx = g_isi_modem_by_name(ifname);
+	if (idx == NULL) {
+		DBG("Interface=%s: %s", ifname, strerror(errno));
+		return -errno;
+	}
+
+	if (n900_gpio_probe(idx, n900_modem_power_cb, modem) != 0) {
+		DBG("gpio for %s: %s", ifname, strerror(errno));
+		return -errno;
+	}
+
+	isi = g_new0(struct isi_data, 1);
+	if (isi == NULL) {
+		n900_gpio_remove(modem);
+		return -ENOMEM;
+	}
+
+	ofono_modem_set_data(isi->modem = modem, isi);
+
+	isi->idx = idx;
+	isi->ifname = ifname;
+	isi->client = g_isi_client_create(isi->idx, PN_MTC);
+
+	return 0;
+}
+
+static void n900_modem_remove(struct ofono_modem *modem)
+{
+	struct isi_data *isi = ofono_modem_get_data(modem);
+
+	DBG("");
+
+	if (isi == NULL)
+		return;
+
+	n900_gpio_remove(modem);
+	if (isi->timeout)
+		g_source_remove(isi->timeout);
+	g_isi_client_destroy(isi->client);
+	g_free(isi);
+}
+
+static gboolean mtc_state_cb(GIsiClient *client,
+				const void *restrict data, size_t len,
+				uint16_t object, void *opaque)
+{
+	struct isi_cb_data *cbd = opaque;
+	struct ofono_modem *modem = cbd->user;
+	ofono_modem_online_cb_t cb = cbd->cb;
+	struct isi_data *isi = ofono_modem_get_data(modem);
+	const unsigned char *msg = data;
+
+	if (!msg) {
+		DBG("ISI client error: %d", g_isi_client_error(client));
+		goto err;
+	}
+
+	if (len < 3 || msg[0] != MTC_STATE_RESP)
+		return FALSE;
+
+	DBG("cause: %s (0x%02X)", mtc_isi_cause_name(msg[1]), msg[1]);
+
+	if (msg[1] == MTC_OK) {
+		isi->online_cbd = cbd;
+		return TRUE;
+	}
+
+err:
+	if (msg && msg[1] == MTC_ALREADY_ACTIVE)
+		CALLBACK_WITH_SUCCESS(cb, cbd->data);
+	else
+		CALLBACK_WITH_FAILURE(cb, cbd->data);
+
+	g_free(cbd);
+	return TRUE;
+}
+
+static void n900_modem_set_online(struct ofono_modem *modem,
+					ofono_bool_t online,
+					ofono_modem_online_cb_t cb, void *data)
+{
+	struct isi_data *isi = ofono_modem_get_data(modem);
+	const unsigned char req[] = {
+		MTC_STATE_REQ, online ? MTC_NORMAL : MTC_RF_INACTIVE, 0x00
+	};
+	struct isi_cb_data *cbd;
+
+	DBG("(%p) with %s", modem, isi->ifname);
+
+	if (isi->power_state != POWER_ON_STATE)
+		goto error;
+	if (isi->mtc_state == MTC_SELFTEST_FAIL)
+		goto error;
+
+	cbd = isi_cb_data_new(modem, cb, data);
+	if (!cbd)
+		goto error;
+
+	isi->online = online;
+
+	if (g_isi_request_make(isi->client, req, sizeof(req), MTC_TIMEOUT,
+				mtc_state_cb, cbd))
+		return;
+
+	g_free(cbd);
+error:
+	CALLBACK_WITH_FAILURE(cb, data);
+}
+
+static void n900_modem_pre_sim(struct ofono_modem *modem)
+{
+	struct isi_data *isi = ofono_modem_get_data(modem);
+
+	DBG("");
+
+	isi->infoserver = isi_infoserver_create(isi->modem, isi->idx);
+
+	ofono_sim_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_devinfo_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_voicecall_create(isi->modem, 0, "isimodem", isi->idx);
+}
+
+static void n900_modem_post_sim(struct ofono_modem *modem)
+{
+	struct isi_data *isi = ofono_modem_get_data(modem);
+
+	DBG("");
+
+	ofono_phonebook_create(isi->modem, 0, "isimodem", isi->idx);
+}
+
+static void n900_modem_post_online(struct ofono_modem *modem)
+{
+	struct isi_data *isi = ofono_modem_get_data(modem);
+	struct ofono_gprs *gprs;
+	struct ofono_gprs_context *gc;
+
+	DBG("");
+
+	ofono_netreg_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_sms_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_cbs_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_ssn_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_ussd_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_call_forwarding_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_call_settings_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_call_barring_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_call_meter_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_radio_settings_create(isi->modem, 0, "isimodem", isi->idx);
+	gprs = ofono_gprs_create(isi->modem, 0, "isimodem", isi->idx);
+	gc = ofono_gprs_context_create(isi->modem, 0, "isimodem", isi->idx);
+
+	if (gprs && gc)
+		ofono_gprs_add_context(gprs, gc);
+	else
+		DBG("Failed to add context");
+}
+
+static int n900_modem_enable(struct ofono_modem *modem)
+{
+	struct isi_data *isi = ofono_modem_get_data(modem);
+	DBG("modem=%p with %p", modem, isi ? isi->ifname : NULL);
+	return n900_gpio_enable(modem);
+}
+
+static int n900_modem_disable(struct ofono_modem *modem)
+{
+	struct isi_data *isi = ofono_modem_get_data(modem);
+	DBG("modem=%p with %p", modem, isi ? isi->ifname : NULL);
+	return n900_gpio_disable(modem);
+}
+
+static struct ofono_modem_driver driver = {
+	.name = "n900",
+	.probe = n900_modem_probe,
+	.remove = n900_modem_remove,
+	.enable = n900_modem_enable,
+	.disable = n900_modem_disable,
+	.set_online = n900_modem_set_online,
+	.pre_sim = n900_modem_pre_sim,
+	.post_sim = n900_modem_post_sim,
+	.post_online = n900_modem_post_online,
+};
+
+/*
+ * Plug in n900 modem when phonet* phonet interface is added/removed
+ *
+ * Note: this functions assumes the kernel does not configure the
+ * interface and the phonet routes. It also depends on kernel using
+ * magic interface name phonet0 for the hsi link to the modem.
+ */
+static void phonet_status_cb(GIsiModem *idx,
+				GPhonetLinkState st,
+				char const ifname[],
+				void *data)
+{
+	struct ofono_modem *modem;
+	int error;
+
+	DBG("Phonet link %s (%u) is %s",
+		ifname, g_isi_modem_index(idx),
+		st == PN_LINK_REMOVED ? "removed" :
+		st == PN_LINK_DOWN ? "down" : "up");
+
+	if (strcmp("phonet0", ifname))
+		return;
+
+	if (st == PN_LINK_REMOVED)
+		return;
+
+	if (g_pn_netlink_by_modem(idx)) {
+		DBG("Modem for interface %s already exists", ifname);
+		return;
+	}
+
+	error = g_pn_netlink_set_address(idx, PN_DEV_SOS);
+	if (error && error != -EEXIST) {
+		DBG("g_pn_netlink_set_address: %s\n", strerror(-error));
+		return;
+	}
+
+	g_pn_netlink_add_route(idx, PN_DEV_HOST);
+
+	modem = ofono_modem_create("n900", "n900");
+	if (!modem)
+		return;
+
+	ofono_modem_set_string(modem, "Interface", ifname);
+
+	if (ofono_modem_register(modem) == 0)
+		DBG("Done regging modem %s", ofono_modem_get_path(modem));
+	else
+		ofono_modem_remove(modem);
+}
+
+static GPhonetNetlink *link;
+
+static int n900modem_init(void)
+{
+	ofono_modem_driver_register(&driver);
+
+	link = g_pn_netlink_start(NULL, phonet_status_cb, NULL);
+
+	return 0;
+}
+
+static void n900modem_exit(void)
+{
+	g_pn_netlink_stop(link);
+	link = NULL;
+
+	ofono_modem_driver_unregister(&driver);
+}
+
+OFONO_PLUGIN_DEFINE(n900, "Nokia N900 modem driver", VERSION,
+		OFONO_PLUGIN_PRIORITY_DEFAULT, n900modem_init, n900modem_exit)
diff --git a/plugins/n900gpio.c b/plugins/n900gpio.c
new file mode 100644
index 0000000..9951c4c
--- /dev/null
+++ b/plugins/n900gpio.c
@@ -0,0 +1,796 @@
+/*
+ * This file is part of oFono - Open Source Telephony
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * 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 <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <gisi/netlink.h>
+#include <glib.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/modem.h>
+#include <ofono/log.h>
+
+#include <drivers/isimodem/debug.h>
+#include "n900gpio.h"
+
+#define GPIO_SWITCH	"/sys/devices/platform/gpio-switch"
+#define DEV_CMT		"/dev/cmt"
+
+enum rapu_type {
+	RAPU1, RAPU2
+};
+
+enum {
+	RESET_RETRIES = 5,
+	POWER_ON_RETRIES = 10
+};
+
+enum phonet_state {
+	PHONET_LINK_NONE = 0,
+	PHONET_LINK_DOWN,
+	PHONET_LINK_UP,
+};
+
+enum gpio_power_event {
+	PHONET_LINK_UP_EVENT = 1,
+	PHONET_LINK_DOWN_EVENT,
+
+	POWER_ON_EVENT,
+
+	POWER_ON_TIMEOUT_EVENT,
+	POWER_REBOOT_TIMEOUT_EVENT,
+
+	POWER_OFF_EVENT,
+	POWER_OFF_IMMEDIATELY_EVENT,
+
+	POWER_OFF_TIMEOUT_EVENT,
+	POWER_OFF_COMPLETE_EVENT,
+};
+
+struct n900_gpio {
+	GPhonetNetlink *link;
+
+	n900_gpio_callback *callback;
+	void *data;
+
+	enum n900_power_state state;
+
+	enum phonet_state current, target;
+
+	unsigned retries;
+
+	enum gpio_power_event timer_event;
+	guint timeout;
+	guint pollout;
+
+	enum rapu_type rapu;
+
+	unsigned have_gpio_switch:1;
+	unsigned have_cmt_en:1;
+	unsigned have_cmt_rst_rq:1;
+	unsigned have_cmt_rst:1;
+	unsigned have_cmt_bsi:1;
+	unsigned have_cmt_apeslpx:1;
+
+	unsigned reset_in_progress:1;
+	unsigned startup_in_progress:1;
+} self;
+
+#define _(X) case X: return #X
+
+static inline char const *gpio_power_event_name(enum gpio_power_event value)
+{
+	switch (value) {
+		_(PHONET_LINK_UP_EVENT);
+		_(PHONET_LINK_DOWN_EVENT);
+		_(POWER_ON_EVENT);
+		_(POWER_ON_TIMEOUT_EVENT);
+		_(POWER_REBOOT_TIMEOUT_EVENT);
+		_(POWER_OFF_EVENT);
+		_(POWER_OFF_IMMEDIATELY_EVENT);
+		_(POWER_OFF_TIMEOUT_EVENT);
+		_(POWER_OFF_COMPLETE_EVENT);
+	}
+	return "<UNKNOWN>";
+}
+
+char const *n900_power_state_name(enum n900_power_state value)
+{
+	switch (value) {
+		_(POWER_NONE_STATE);
+		_(POWER_ON_STARTED_STATE);
+		_(POWER_ON_STATE);
+		_(POWER_ON_RESET_STATE);
+		_(POWER_ON_FAILED_STATE);
+		_(POWER_OFF_STARTED_STATE);
+		_(POWER_OFF_WAITING_STATE);
+		_(POWER_OFF_STATE);
+	}
+	return "<UNKNOWN>";
+}
+
+#undef _
+
+static void gpio_power_state_machine(enum gpio_power_event event);
+static void gpio_power_set_state(enum n900_power_state new_state);
+
+static int file_exists(char const *filename)
+{
+	struct stat st;
+
+	return stat(filename, &st) == 0;
+}
+
+static int dir_exists(char const *filename)
+{
+	struct stat st;
+
+	return stat(filename, &st) == 0 && S_ISDIR(st.st_mode);
+}
+
+static int file_write(char const *filename, char const *output)
+{
+	FILE *f;
+
+	f = fopen(filename, "r+");
+	if (!f) {
+		DBG("%s: %s (%d)", filename, strerror(errno), errno);
+		return -1;
+	}
+
+	fputs(output, f);
+
+	return fclose(f);
+}
+
+static int gpio_write(char *line, int value)
+{
+	char filename[256];
+
+	DBG("(\"%s\", \"%s\")", line, value ? "active" : "inactive");
+
+	if (self.have_gpio_switch) {
+		snprintf(filename, sizeof filename, "%s/%s/%s",
+				GPIO_SWITCH, line, "state");
+		return file_write(filename, value ? "active" : "inactive");
+	} else {
+		snprintf(filename, sizeof filename, "%s/%s/%s",
+				DEV_CMT, line, "value");
+		return file_write(filename, value ? "1" : "0");
+	}
+}
+
+#define GPIO_WRITE(line, value) \
+	(self.have_ ## line ? gpio_write(#line, value) : 0)
+
+static int gpio_probe(char const *line)
+{
+	char filename[256];
+	int result;
+
+	if (self.have_gpio_switch)
+		snprintf(filename, sizeof filename,
+				"%s/%s/state", GPIO_SWITCH, line);
+	else
+		snprintf(filename, sizeof filename,
+				"%s/%s/value", DEV_CMT, line);
+
+	result = file_exists(filename);
+
+	DBG("%s: %s", line, result ? "found" : "not found");
+
+	return result;
+}
+
+/*
+ * Modem start up function
+ * Sets all lines down and leaves "power key" pressed
+ * (power key must be released after some time)
+ */
+static void gpio_start_modem_power_on(void)
+{
+	DBG("");
+
+	if (self.startup_in_progress)
+		return;
+	self.startup_in_progress = 1;
+
+	GPIO_WRITE(cmt_apeslpx, 0);	/* skip flash mode */
+	GPIO_WRITE(cmt_rst_rq, 0);	/* prevent current drain */
+
+	switch (self.rapu) {
+	case RAPU2:
+		GPIO_WRITE(cmt_en, 0);
+		/* 15 ms needed for ASIC poweroff */
+		usleep(20000);
+		GPIO_WRITE(cmt_en, 1);
+		break;
+
+	case RAPU1:
+		/* toggle BSI visible to CMT */
+		GPIO_WRITE(cmt_bsi, 0);
+		GPIO_WRITE(cmt_rst, 0);	/* Assert PURX */
+		GPIO_WRITE(cmt_en, 1);	/* Press "power key" */
+		GPIO_WRITE(cmt_rst, 1);	/* Release CMT to boot */
+		break;
+	}
+
+	GPIO_WRITE(cmt_rst_rq, 1);
+}
+
+static void gpio_finish_modem_power_on(void)
+{
+	DBG("");
+
+	if (!self.startup_in_progress)
+		return;
+	self.startup_in_progress = 0;
+
+	switch (self.rapu) {
+	case RAPU2:
+		break;
+
+	case RAPU1:
+		GPIO_WRITE(cmt_en, 0);	/* release "power key" */
+		break;
+	}
+}
+
+static void gpio_start_modem_reset(void)
+{
+	DBG("");
+
+	if (self.reset_in_progress)
+		return;
+	self.reset_in_progress = 1;
+
+	if (self.have_cmt_rst_rq) {
+		GPIO_WRITE(cmt_rst_rq, 0); /* Just in case */
+		GPIO_WRITE(cmt_rst_rq, 1);
+	} else
+		gpio_start_modem_power_on();
+}
+
+static void gpio_finish_modem_reset(void)
+{
+	DBG("");
+
+	if (!self.reset_in_progress)
+		return;
+	self.reset_in_progress = 0;
+	gpio_finish_modem_power_on();
+}
+
+static void gpio_finish_modem_power_off(void)
+{
+	DBG("");
+
+	if (self.reset_in_progress)
+		gpio_finish_modem_reset();
+	if (self.startup_in_progress)
+		gpio_finish_modem_power_on();
+
+	GPIO_WRITE(cmt_apeslpx, 0);	/* skip flash mode */
+	GPIO_WRITE(cmt_rst_rq, 0);	/* prevent current drain */
+
+	switch (self.rapu) {
+	case RAPU2:
+		GPIO_WRITE(cmt_en, 0);	/* Power off */
+		break;
+
+	case RAPU1:
+		GPIO_WRITE(cmt_rst, 0);	/* force CMT to reset state */
+		GPIO_WRITE(cmt_en, 0);	/* release "power key" */
+		GPIO_WRITE(cmt_rst, 1);	/* release CMT to be powered
+							off by bootloader */
+		break;
+	}
+}
+
+static gboolean gpio_power_timer_cb(gpointer user)
+{
+	self.timeout = 0;
+
+	if (self.timer_event)
+		gpio_power_state_machine(self.timer_event);
+
+	return FALSE;
+}
+
+
+static void gpio_power_state_machine(enum gpio_power_event event)
+{
+	enum n900_power_state new_state;
+
+	DBG("(%s) @ state %s",
+		gpio_power_event_name(event),
+		n900_power_state_name(self.state));
+
+	switch (event) {
+	case POWER_ON_EVENT:
+		self.target = PHONET_LINK_UP;
+
+		if (self.current == PHONET_LINK_NONE)
+			return;
+
+		switch (self.state) {
+		case POWER_ON_STARTED_STATE:
+		case POWER_ON_RESET_STATE:
+		case POWER_ON_STATE:
+			/* Do nothing */
+			break;
+		case POWER_OFF_STARTED_STATE:
+			/* Do nothing */
+			break;
+		case POWER_NONE_STATE:
+		case POWER_OFF_WAITING_STATE:
+		case POWER_OFF_STATE:
+		case POWER_ON_FAILED_STATE:
+			gpio_power_set_state(POWER_ON_STARTED_STATE);
+			break;
+		}
+		return;
+
+	case PHONET_LINK_DOWN_EVENT:
+		switch (self.target) {
+		case PHONET_LINK_DOWN:
+		case PHONET_LINK_NONE:
+		default:
+			if (self.state == POWER_OFF_STATE ||
+				self.state == POWER_NONE_STATE)
+				new_state = POWER_OFF_STATE;
+			else
+				new_state = POWER_OFF_WAITING_STATE;
+			gpio_power_set_state(new_state);
+			return;
+		case PHONET_LINK_UP:
+			break;
+		}
+
+		switch (self.state) {
+		case POWER_NONE_STATE:
+			/* first connection down event => start modem */
+			gpio_power_set_state(POWER_ON_STARTED_STATE);
+			break;
+
+		case POWER_ON_STARTED_STATE:
+		case POWER_ON_RESET_STATE:
+			break;
+
+		default:
+			self.retries = 0;
+			gpio_power_set_state(POWER_ON_RESET_STATE);
+			break;
+		}
+		return;
+
+	case POWER_ON_TIMEOUT_EVENT:
+		if (self.target == PHONET_LINK_DOWN)
+			new_state = POWER_OFF_STARTED_STATE;
+		else if (self.retries <= POWER_ON_RETRIES)
+			new_state = POWER_ON_STARTED_STATE;
+		else
+			new_state = POWER_ON_FAILED_STATE;
+		gpio_power_set_state(new_state);
+		return;
+
+	case POWER_REBOOT_TIMEOUT_EVENT:
+		/* Modem is not rebooting itself - try to powercycle it */
+		if (self.target == PHONET_LINK_DOWN)
+			new_state = POWER_OFF_STARTED_STATE;
+		else if (self.retries <= RESET_RETRIES)
+			new_state = POWER_ON_RESET_STATE;
+		else
+			new_state = POWER_ON_STARTED_STATE;
+		gpio_power_set_state(new_state);
+		return;
+
+	case PHONET_LINK_UP_EVENT:
+		switch (self.state) {
+		case POWER_NONE_STATE:
+			return;
+
+		case POWER_ON_STARTED_STATE:
+		case POWER_ON_RESET_STATE:
+			break;
+
+		case POWER_ON_STATE:
+			return;
+
+		case POWER_OFF_STARTED_STATE:
+		case POWER_OFF_WAITING_STATE:
+		case POWER_OFF_STATE:
+		case POWER_ON_FAILED_STATE:
+			DBG("LINK_UP event while "
+				"modem should be powered off");
+			/* should never come here */
+			break;
+		}
+		if (self.target == PHONET_LINK_DOWN)
+			gpio_power_set_state(POWER_OFF_STARTED_STATE);
+		else
+			gpio_power_set_state(POWER_ON_STATE);
+		return;
+
+	case POWER_OFF_EVENT:
+		self.target = PHONET_LINK_DOWN;
+
+		switch (self.state) {
+		case POWER_ON_STARTED_STATE:
+		case POWER_ON_RESET_STATE:
+			/* Do nothing until a timer expires */
+			break;
+		case POWER_ON_STATE:
+			gpio_power_set_state(POWER_OFF_STARTED_STATE);
+			break;
+		case POWER_OFF_STARTED_STATE:
+		case POWER_OFF_WAITING_STATE:
+		case POWER_OFF_STATE:
+			/* Do nothing */
+			break;
+		case POWER_NONE_STATE:
+		case POWER_ON_FAILED_STATE:
+			gpio_power_set_state(POWER_OFF_STATE);
+			break;
+		}
+		return;
+
+	case POWER_OFF_IMMEDIATELY_EVENT:
+		gpio_power_set_state(POWER_OFF_STATE);
+		return;
+
+	case POWER_OFF_TIMEOUT_EVENT:
+		DBG("CMT power off timed out");
+		gpio_power_set_state(POWER_OFF_STATE);
+		return;
+
+	case POWER_OFF_COMPLETE_EVENT:
+		if (self.state == POWER_OFF_WAITING_STATE) {
+			DBG("Modem shutdown complete");
+			gpio_power_set_state(POWER_OFF_STATE);
+		}
+		return;
+	}
+
+	DBG("Event %s (%d) not handled", gpio_power_event_name(event), event);
+}
+
+
+static void gpio_power_set_state(enum n900_power_state new_state)
+{
+	enum n900_power_state old_state = self.state;
+	unsigned timeout = 0;
+	enum gpio_power_event timer_event;
+
+	DBG("(%s)@(%s)%s",
+		n900_power_state_name(new_state),
+		n900_power_state_name(old_state),
+		new_state == old_state ? " - already" : "");
+
+	switch (old_state) {
+	case POWER_ON_STARTED_STATE:
+		gpio_finish_modem_power_on();
+		break;
+	case POWER_ON_RESET_STATE:
+		gpio_finish_modem_reset();
+		break;
+	default:
+		break;
+	}
+
+	if (self.timeout) {
+		g_source_remove(self.timeout), self.timeout = 0;
+		self.timer_event = 0;
+	}
+
+	if (old_state == new_state &&
+		new_state != POWER_ON_STARTED_STATE &&
+		new_state != POWER_ON_RESET_STATE)
+		return;
+
+	switch (self.state = new_state) {
+	case POWER_NONE_STATE:
+		break;
+
+	case POWER_ON_STARTED_STATE:
+		self.retries++;
+		/* Maximum time modem power on procedure on can take */
+		timeout = 5000;
+		timer_event = POWER_ON_TIMEOUT_EVENT;
+		gpio_start_modem_power_on();
+		break;
+
+	case POWER_ON_RESET_STATE:
+		DBG("Starting modem restart timeout");
+		/* Time allowed for CMT to restart after crash */
+		timeout = 5000;
+		timer_event = POWER_REBOOT_TIMEOUT_EVENT;
+		if (self.retries++ > 0)
+			gpio_start_modem_reset();
+		break;
+
+	case POWER_ON_STATE:
+		DBG("Power on");
+		self.retries = 0;
+		break;
+
+	case POWER_OFF_STARTED_STATE:
+		DBG("Starting power off");
+		/* Maximum time modem power_off can take */
+		timeout = 6150;
+		timer_event = POWER_OFF_TIMEOUT_EVENT;
+		break;
+
+	case POWER_OFF_WAITING_STATE:
+		gpio_finish_modem_power_off();
+		DBG("Waiting to modem to settle down");
+		/* Cooling time after power off */
+		timeout = 1000;
+		timer_event = POWER_OFF_COMPLETE_EVENT;
+		break;
+
+	case POWER_OFF_STATE:
+		if (old_state != POWER_OFF_WAITING_STATE &&
+			old_state != POWER_ON_FAILED_STATE)
+			gpio_finish_modem_power_off();
+		break;
+
+	case POWER_ON_FAILED_STATE:
+		DBG("Link to modem cannot be established, giving up");
+		gpio_finish_modem_power_off();
+		break;
+	}
+
+	if (timeout) {
+		self.timer_event = timer_event;
+		self.timeout = g_timeout_add(timeout,
+					gpio_power_timer_cb, NULL);
+	}
+
+	self.callback(new_state, self.data);
+}
+
+static void phonet_status_cb(GIsiModem *idx,
+				GPhonetLinkState st,
+				char const *ifname,
+				void *dummy)
+{
+	DBG("Link %s (%u) is %s",
+		ifname, g_isi_modem_index(idx),
+		st == PN_LINK_REMOVED ? "removed" :
+		st == PN_LINK_DOWN ? "down" : "up");
+
+	(void)dummy;
+
+	if (st == PN_LINK_UP) {
+		if (self.current == PHONET_LINK_UP)
+			return;
+		self.current = PHONET_LINK_UP;
+
+		/* link is up - we can lower cmt_rst_rq */
+		GPIO_WRITE(cmt_rst_rq, 0);
+
+		gpio_power_state_machine(PHONET_LINK_UP_EVENT);
+	} else {
+		if (self.current == PHONET_LINK_DOWN)
+			return;
+		self.current = PHONET_LINK_DOWN;
+
+		gpio_power_state_machine(PHONET_LINK_DOWN_EVENT);
+	}
+}
+
+static int gpio_probe_links(void)
+{
+	char const *gpiodir = "/sys/class/gpio";
+	char const *cmtdir = "/dev/cmt";
+	DIR *gpio;
+	struct dirent *d, entry[1];
+
+	if (file_exists(cmtdir)) {
+		DBG("Using %s", cmtdir);
+		return 0;
+	}
+
+	DBG("Using %s: trying to make links to %s", gpiodir, cmtdir);
+
+	if (!dir_exists(cmtdir)) {
+		if (mkdir(cmtdir, 0755) == -1) {
+			DBG("%s: %s", cmtdir, strerror(errno));
+			return -(errno = ENODEV);
+		}
+	}
+
+	gpio = opendir(gpiodir);
+	if (gpio == NULL) {
+		DBG("%s: %s", "gpiodir", strerror(errno));
+		return -(errno = ENODEV);
+	}
+
+	while (readdir_r(gpio, entry, &d) == 0) {
+		char nn[PATH_MAX], name[PATH_MAX], from[PATH_MAX], to[PATH_MAX];
+		FILE *nf;
+		size_t len;
+
+		if (d == NULL)
+			return 0;
+
+		snprintf(nn, sizeof nn, "%s/%s/name", gpiodir, d->d_name);
+
+		nf = fopen(nn, "rb");
+		if (nf == NULL) {
+			DBG("%s: %s", nn, strerror(errno));
+			continue;
+		}
+
+		len = fread(name, sizeof name, 1, nf);
+
+		if (ferror(nf)) {
+			DBG("read from %s: %s", nn, strerror(errno));
+			fclose(nf);
+			continue;
+		}
+
+		fclose(nf);
+
+		if (len < 4)
+			continue;
+
+		name[--len] = '\0';
+
+		if (strncmp(name, "cmt_", 4))
+			continue;
+
+		snprintf(from, sizeof from, "%s/%s", gpiodir, d->d_name);
+		snprintf(to, sizeof to, "%s/%s", cmtdir, name);
+
+		if (symlink(from, to) == -1)
+			DBG("%s: %s", to, strerror(errno));
+	}
+
+	DBG("%s: %s", "/sys/class/gpio", strerror(errno));
+
+	return -(errno = ENODEV);
+}
+
+
+int n900_gpio_probe(GIsiModem *idx, n900_gpio_callback *callback, void *data)
+{
+	int error;
+
+	if (callback == NULL) {
+		DBG("n900_gpio: %s", "no callback");
+		return -(errno = EFAULT);
+	}
+
+	if (self.callback) {
+		DBG("n900_gpio: %s", strerror(EBUSY));
+		return -(errno = EBUSY);
+	}
+
+	if (g_pn_netlink_by_modem(idx)) {
+		DBG("Phonet link %p: %s", idx, strerror(EBUSY));
+		return -(errno = EBUSY);
+	}
+
+	self.target = PHONET_LINK_NONE;
+	self.have_gpio_switch = file_exists(GPIO_SWITCH);
+
+	if (self.have_gpio_switch) {
+		DBG("Using GPIO switch");
+	} else {
+		error = gpio_probe_links();
+		if (error)
+			return error;
+	}
+
+	/* GPIO lines availability depends on HW and SW versions */
+	self.have_cmt_en = gpio_probe("cmt_en");
+	self.have_cmt_rst_rq = gpio_probe("cmt_rst_rq");
+	self.have_cmt_rst = gpio_probe("cmt_rst");
+	self.have_cmt_bsi = gpio_probe("cmt_bsi");
+	self.have_cmt_apeslpx = gpio_probe("cmt_apeslpx");
+
+	if (!self.have_cmt_en) {
+		DBG("Modem control GPIO lines are not available");
+		memset(&self, 0, sizeof self);
+		return -(errno = ENODEV);
+	}
+
+	if (self.have_cmt_bsi)
+		self.rapu = RAPU1;
+	else
+		self.rapu = RAPU2;
+
+	self.link = g_pn_netlink_start(idx, phonet_status_cb, NULL);
+	if (!self.link) {
+		memset(&self, 0, sizeof self);
+		return -errno;
+	}
+
+	self.callback = callback;
+	self.data = data;
+
+	error = g_pn_netlink_set_address(idx, PN_DEV_SOS);
+	if (error && error != -EEXIST)
+		DBG("g_pn_netlink_set_address: %s\n", strerror(-error));
+
+	error = g_pn_netlink_add_route(idx, PN_DEV_HOST);
+	if (error && error != -ENOTSUP)	/* We get ENOTSUP on Maemo 5 kernel */
+		DBG("g_pn_netlink_add_route: %s\n", strerror(-error));
+
+	return 0;
+}
+
+int n900_gpio_remove(void *data)
+{
+	if (self.data != data)
+		return -EINVAL;
+
+	if (self.link)
+		g_pn_netlink_stop(self.link);
+	if (self.timeout)
+		g_source_remove(self.timeout), self.timeout = 0;
+
+	memset(&self, 0, sizeof self);
+
+	return 0;
+}
+
+int n900_gpio_enable(void *data)
+{
+	if (self.data != data)
+		return -EINVAL;
+
+	if (self.state == POWER_ON_STATE)
+		return 0;
+
+	gpio_power_state_machine(POWER_ON_EVENT);
+
+	return -EINPROGRESS;
+}
+
+int n900_gpio_disable(void *data)
+{
+	if (self.data != data)
+		return -EINVAL;
+
+	if (self.state == POWER_OFF_STATE ||
+		self.state == POWER_ON_FAILED_STATE)
+		return 0;
+
+	gpio_power_state_machine(POWER_OFF_EVENT);
+
+	return -EINPROGRESS;
+}
diff --git a/plugins/n900gpio.h b/plugins/n900gpio.h
new file mode 100644
index 0000000..27be134
--- /dev/null
+++ b/plugins/n900gpio.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of oFono - Open Source Telephony
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * 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 __N900_GPIO_H
+#define __N900_GPIO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum n900_power_state {
+	POWER_NONE_STATE,
+
+	POWER_ON_STARTED_STATE,
+	POWER_ON_STATE,
+	POWER_ON_RESET_STATE,
+	POWER_ON_FAILED_STATE,
+	POWER_OFF_STARTED_STATE,
+	POWER_OFF_WAITING_STATE,
+	POWER_OFF_STATE,
+};
+
+typedef void n900_gpio_callback(enum n900_power_state, void *opaque);
+
+int n900_gpio_probe(GIsiModem *idx, n900_gpio_callback *callback, void *data);
+int n900_gpio_enable(void *opaque);
+int n900_gpio_disable(void *opaque);
+int n900_gpio_remove(void *opaque);
+
+char const *n900_power_state_name(enum n900_power_state value);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* __N900_GPIO_H */
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [n900 PATCH 5/5] n900maemo: modem driver plugin for N900 with Maemo
  2010-09-15 16:59       ` [n900 PATCH 4/5] n900: modem driver plugin for Nokia N900 Pekka.Pessi
@ 2010-09-15 16:59         ` Pekka.Pessi
  0 siblings, 0 replies; 13+ messages in thread
From: Pekka.Pessi @ 2010-09-15 16:59 UTC (permalink / raw)
  To: ofono

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

From: Pekka Pessi <ppessi@hamsa.research.nokia.com>

This modem plugin is used on N900 running Maemo userspace already
controlling the phonet link and the N900 modem (csd and sscd).

The plugin uses the isigen driver for the N900 internal modem.

The n900maemo is compiled (while the normal n900 modem driver is
disabled) if ofono is configured with with --enable-n900modem option.
---
 Makefile.am         |    9 +++++
 configure.ac        |    5 +++
 plugins/n900maemo.c |   99 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 113 insertions(+), 0 deletions(-)
 create mode 100644 plugins/n900maemo.c

diff --git a/Makefile.am b/Makefile.am
index d643ca8..23f0edb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -132,6 +132,8 @@ isigen_sources = plugins/isigen.c
 
 n900_sources = plugins/n900.c plugins/n900gpio.h plugins/n900gpio.c
 
+n900maemo_sources = plugins/n900maemo.c
+
 if ISIMODEM
 builtin_modules += isimodem
 builtin_sources += $(isimodem_sources)
@@ -139,8 +141,14 @@ builtin_sources += $(isimodem_sources)
 builtin_modules += isigen
 builtin_sources += $(isigen_sources)
 
+if !N900MAEMO
 builtin_modules += n900
 builtin_sources += $(n900_sources)
+else
+builtin_modules += n900maemo
+builtin_sources += $(n900maemo_sources)
+endif
+
 endif
 
 if ATMODEM
@@ -389,6 +397,7 @@ EXTRA_DIST = src/genbuiltin plugins/example_history.c $(doc_files) \
 				$(isimodem_sources) \
 				$(isigen_sources) \
 				$(n900_sources) \
+				$(n900maemo_sources) \
 				$(test_scripts) $(conf_files) $(udev_files)
 
 dist_man_MANS = doc/ofonod.8
diff --git a/configure.ac b/configure.ac
index bd1dacb..c79a88b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -140,6 +140,11 @@ AC_ARG_ENABLE(isimodem, AC_HELP_STRING([--disable-isimodem],
 					[enable_isimodem=${enableval}])
 AM_CONDITIONAL(ISIMODEM, test "${enable_isimodem}" != "no")
 
+AC_ARG_ENABLE(n900maemo, AC_HELP_STRING([--enable-n900maemo],
+				[Enable support for N900 running Maemo]),
+					[enable_n900maemo=${enableval}])
+AM_CONDITIONAL(N900MAEMO, test "${enable_n900maemo}" = "yes")
+
 AC_ARG_ENABLE(atmodem, AC_HELP_STRING([--disable-atmodem],
 				[disable ETSI AT modem support]),
 					[enable_atmodem=${enableval}])
diff --git a/plugins/n900maemo.c b/plugins/n900maemo.c
new file mode 100644
index 0000000..4728edb
--- /dev/null
+++ b/plugins/n900maemo.c
@@ -0,0 +1,99 @@
+/*
+ * This file is part of oFono - Open Source Telephony
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * 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 <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+
+#include <gisi/client.h>
+#include <gisi/netlink.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/log.h>
+#include <ofono/modem.h>
+
+#include "drivers/isimodem/isimodem.h"
+#include "drivers/isimodem/debug.h"
+
+static GPhonetNetlink *link;
+
+/*
+ * Add or remove phonet0 interface is added/removed
+ */
+static void phonet0_status_cb(GIsiModem *idx,
+				GPhonetLinkState st,
+				char const ifname[],
+				void *data)
+{
+	struct ofono_modem *modem;
+	int error;
+
+	if (strcmp("phonet0", ifname))
+		return;
+
+	DBG("Phonet link %s (%u) is %s",
+		ifname, g_isi_modem_index(idx),
+		st == PN_LINK_REMOVED ? "removed" :
+		st == PN_LINK_DOWN ? "down" : "up");
+
+	if (st == PN_LINK_REMOVED)
+		return;
+
+	if (g_pn_netlink_by_modem(idx)) {
+		DBG("Modem for interface %s already exists", ifname);
+		return;
+	}
+
+	modem = ofono_modem_create("n900", "isigen");
+	if (!modem)
+		return;
+
+	ofono_modem_set_string(modem, "Interface", ifname);
+
+	if (ofono_modem_register(modem) == 0)
+		DBG("Done regging modem %s", ofono_modem_get_path(modem));
+	else
+		ofono_modem_remove(modem);
+}
+
+static int n900maemo_init(void)
+{
+	link = g_pn_netlink_start(NULL, phonet0_status_cb, NULL);
+
+	return 0;
+}
+
+static void n900maemo_exit(void)
+{
+	g_pn_netlink_stop(link);
+	link = NULL;
+}
+
+OFONO_PLUGIN_DEFINE(n900maemo, "Hotplug driver for N900 modem with Maemo",
+			VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT,
+			n900maemo_init, n900maemo_exit)
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [n900 PATCH 2/5] isigen: generic modem driver plugin for isimodems
  2010-09-15 16:59   ` [n900 PATCH 2/5] isigen: generic modem driver plugin for isimodems Pekka.Pessi
  2010-09-15 16:59     ` [n900 PATCH 3/5] isimodem: remove the modem driver parts Pekka.Pessi
@ 2010-09-15 18:07     ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
  2010-09-15 21:27       ` Pekka Pessi
  1 sibling, 1 reply; 13+ messages in thread
From: =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont @ 2010-09-15 18:07 UTC (permalink / raw)
  To: ofono

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


   Hello

Please. Don't put netlink *settings* in oFono. This kills the whole idea of
having a common socket stack that can be shared by several processes. If
you want to run against the Maemo kernel, then you have phonet-utils and
sscd taking care of that anyway. As for the Meego kernel, it should get a
up-to-date and patched Phonet stack as needed.

-- 
Rémi Denis-Courmont
http://www.remlab.net
http://fi.linkedin.com/in/remidenis


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [n900 PATCH 2/5] isigen: generic modem driver plugin for isimodems
  2010-09-15 18:07     ` [n900 PATCH 2/5] isigen: generic modem driver plugin for isimodems =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
@ 2010-09-15 21:27       ` Pekka Pessi
  2010-09-15 22:00         ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
  0 siblings, 1 reply; 13+ messages in thread
From: Pekka Pessi @ 2010-09-15 21:27 UTC (permalink / raw)
  To: ofono

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

Hi Rémi,

2010/9/15 Rémi Denis-Courmont <remi@remlab.net>:
> Please. Don't put netlink *settings* in oFono. This kills the whole idea of
> having a common socket stack that can be shared by several processes. If
> you want to run against the Maemo kernel, then you have phonet-utils and
> sscd taking care of that anyway. As for the Meego kernel, it should get a
> up-to-date and patched Phonet stack as needed.

I'm all for including settings as udev rules and driving the plugins
from udev. That is the goal if and when we have up-to-date kernel, but
we are not there yet.

-- 
Pekka.Pessi mail at nokia.com

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [n900 PATCH 2/5] isigen: generic modem driver plugin for isimodems
  2010-09-15 21:27       ` Pekka Pessi
@ 2010-09-15 22:00         ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
  2010-09-16  6:02           ` Aki Niemi
  0 siblings, 1 reply; 13+ messages in thread
From: =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont @ 2010-09-15 22:00 UTC (permalink / raw)
  To: ofono

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


On Thu, 16 Sep 2010 00:27:00 +0300, Pekka Pessi <ppessi@gmail.com> wrote:
> 2010/9/15 Rémi Denis-Courmont <remi@remlab.net>:
>> Please. Don't put netlink *settings* in oFono. This kills the whole idea
>> of having a common socket stack that can be shared by several processes.
>> If you want to run against the Maemo kernel, then you have phonet-utils
>> and sscd taking care of that anyway. As for the Meego kernel, it should
>> get a up-to-date and patched Phonet stack as needed.
> 
> I'm all for including settings as udev rules and driving the plugins
> from udev.

Right.

> That is the goal if and when we have up-to-date kernel, but
> we are not there yet.

I don't see the point of adding temporary cruft to the main oFono
repository then.

-- 
Rémi Denis-Courmont
http://www.remlab.net
http://fi.linkedin.com/in/remidenis


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [n900 PATCH 2/5] isigen: generic modem driver plugin for isimodems
  2010-09-15 22:00         ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
@ 2010-09-16  6:02           ` Aki Niemi
  2010-09-16  6:26             ` Marcel Holtmann
  0 siblings, 1 reply; 13+ messages in thread
From: Aki Niemi @ 2010-09-16  6:02 UTC (permalink / raw)
  To: ofono

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

Hi Rémi,

2010/9/16 Rémi Denis-Courmont <remi@remlab.net>:
>> That is the goal if and when we have up-to-date kernel, but
>> we are not there yet.
>
> I don't see the point of adding temporary cruft to the main oFono
> repository then.

Well, I see value in having oFono upstream work as-is with the current
MeeGo kernel. The plugin could of course reside somewhere else, but
that is just adding extra work for packagers. And it's not like we
can't fix the plugin once MeeGo has a proper kernel in place.

Cheers,
Aki

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [n900 PATCH 2/5] isigen: generic modem driver plugin for isimodems
  2010-09-16  6:02           ` Aki Niemi
@ 2010-09-16  6:26             ` Marcel Holtmann
  2010-09-16 23:45               ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
  0 siblings, 1 reply; 13+ messages in thread
From: Marcel Holtmann @ 2010-09-16  6:26 UTC (permalink / raw)
  To: ofono

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

Hi Aki,

> >> That is the goal if and when we have up-to-date kernel, but
> >> we are not there yet.
> >
> > I don't see the point of adding temporary cruft to the main oFono
> > repository then.
> 
> Well, I see value in having oFono upstream work as-is with the current
> MeeGo kernel. The plugin could of course reside somewhere else, but
> that is just adding extra work for packagers. And it's not like we
> can't fix the plugin once MeeGo has a proper kernel in place.

what is the current state of Phonet support (including N900) and the
current MeeGo kernel? Are we missing patches?

Regards

Marcel



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [n900 PATCH 2/5] isigen: generic modem driver plugin for isimodems
  2010-09-16  6:26             ` Marcel Holtmann
@ 2010-09-16 23:45               ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
  2010-09-17  1:18                 ` Marcel Holtmann
  0 siblings, 1 reply; 13+ messages in thread
From: =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont @ 2010-09-16 23:45 UTC (permalink / raw)
  To: ofono

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


On Thu, 16 Sep 2010 15:26:34 +0900, Marcel Holtmann <marcel@holtmann.org>
wrote:
>> >> That is the goal if and when we have up-to-date kernel, but
>> >> we are not there yet.
>> >
>> > I don't see the point of adding temporary cruft to the main oFono
>> > repository then.
>>
>> Well, I see value in having oFono upstream work as-is with the current
>> MeeGo kernel. The plugin could of course reside somewhere else, but
>> that is just adding extra work for packagers. And it's not like we
>> can't fix the plugin once MeeGo has a proper kernel in place.
> 
> what is the current state of Phonet support (including N900) and the
> current MeeGo kernel? Are we missing patches?

I did not fully grasp what the extra Netlink code does. There should be no
need to CONFIGURE the Phonet stack via Netlink. If there is, then it's a
kernel bug.

-- 
Rémi Denis-Courmont
http://www.remlab.net
http://fi.linkedin.com/in/remidenis


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [n900 PATCH 2/5] isigen: generic modem driver plugin for isimodems
  2010-09-16 23:45               ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
@ 2010-09-17  1:18                 ` Marcel Holtmann
  0 siblings, 0 replies; 13+ messages in thread
From: Marcel Holtmann @ 2010-09-17  1:18 UTC (permalink / raw)
  To: ofono

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

Hi Remi,

> >> >> That is the goal if and when we have up-to-date kernel, but
> >> >> we are not there yet.
> >> >
> >> > I don't see the point of adding temporary cruft to the main oFono
> >> > repository then.
> >>
> >> Well, I see value in having oFono upstream work as-is with the current
> >> MeeGo kernel. The plugin could of course reside somewhere else, but
> >> that is just adding extra work for packagers. And it's not like we
> >> can't fix the plugin once MeeGo has a proper kernel in place.
> > 
> > what is the current state of Phonet support (including N900) and the
> > current MeeGo kernel? Are we missing patches?
> 
> I did not fully grasp what the extra Netlink code does. There should be no
> need to CONFIGURE the Phonet stack via Netlink. If there is, then it's a
> kernel bug.

you are the expert here and have to give us some guideline on how we
should use Phonet the right way. If you say that we should remove the
netlink code from oFono, I am all for it.

Regards

Marcel



^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2010-09-17  1:18 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-09-15 16:59 [n900 PATCH 0/5] n900 modem drivers Pekka.Pessi
2010-09-15 16:59 ` [n900 PATCH 1/5] Include isimodem sources always in dist Pekka.Pessi
2010-09-15 16:59   ` [n900 PATCH 2/5] isigen: generic modem driver plugin for isimodems Pekka.Pessi
2010-09-15 16:59     ` [n900 PATCH 3/5] isimodem: remove the modem driver parts Pekka.Pessi
2010-09-15 16:59       ` [n900 PATCH 4/5] n900: modem driver plugin for Nokia N900 Pekka.Pessi
2010-09-15 16:59         ` [n900 PATCH 5/5] n900maemo: modem driver plugin for N900 with Maemo Pekka.Pessi
2010-09-15 18:07     ` [n900 PATCH 2/5] isigen: generic modem driver plugin for isimodems =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
2010-09-15 21:27       ` Pekka Pessi
2010-09-15 22:00         ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
2010-09-16  6:02           ` Aki Niemi
2010-09-16  6:26             ` Marcel Holtmann
2010-09-16 23:45               ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
2010-09-17  1:18                 ` Marcel Holtmann

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.