All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andres Salomon <dilinger@collabora.co.uk>
To: ofono@ofono.org
Subject: [PATCH 1/3] G1: Add initial HTC G1 modem support
Date: Sun, 30 Aug 2009 00:06:56 -0400	[thread overview]
Message-ID: <20090830040656.GA28039@mycelium.queued.net> (raw)

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

This series adds support for the HTC G1 phone (that is, the Google
phone).

G1 plugin is based on generic_at, with a bunch of stuff dropped
and simplified.  We use AT+CFUN=1 for powering on rather than having
a configurable init string.  We also manually set the default state
during init (the G1 appears to start in mode V0 by default).  The
device (/dev/smd0) is hardcoded.
---
 Makefile.am  |    5 +
 configure.ac |    8 ++-
 plugins/g1.c |  309 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 321 insertions(+), 1 deletions(-)
 create mode 100644 plugins/g1.c

diff --git a/Makefile.am b/Makefile.am
index 7ee6536..a2d3569 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -78,6 +78,11 @@ builtin_modules += generic_at
 builtin_sources += plugins/generic_at.c
 endif
 
+if G1MODEM
+builtin_modules += g1
+builtin_sources += plugins/g1.c
+endif
+
 if MAINTAINER_MODE
 builtin_modules += example_history
 builtin_sources += plugins/example_history.c
diff --git a/configure.ac b/configure.ac
index a299a13..5deabb8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -65,10 +65,16 @@ AC_ARG_ENABLE(isimodem, AC_HELP_STRING([--disable-isimodem],
 					[enable_isimodem=${enableval}])
 AM_CONDITIONAL(ISIMODEM, test "${enable_isimodem}" != "no")
 
+AC_ARG_ENABLE(g1, AC_HELP_STRING([--disable-g1],
+				[disable HTC G1 modem support]),
+					[enable_g1=${enableval}])
+AM_CONDITIONAL(G1MODEM, test "${enable_g1}" != "no")
+
 AC_ARG_ENABLE(atmodem, AC_HELP_STRING([--disable-atmodem],
                                 [disable ETSI AT modem support]),
                                         [enable_atmodem=${enableval}])
-AM_CONDITIONAL(ATMODEM, test "${enable_atmodem}" != "no")
+AM_CONDITIONAL(ATMODEM, [test "${enable_atmodem}" != "no" ||
+			test "${enable_g1}" != "no"])
 
 AC_CHECK_LIB(dl, dlopen, dummy=yes,
 			AC_MSG_ERROR(dynamic linking loader is required))
diff --git a/plugins/g1.c b/plugins/g1.c
new file mode 100644
index 0000000..70e4914
--- /dev/null
+++ b/plugins/g1.c
@@ -0,0 +1,309 @@
+/*
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2009  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2009  Collabora Ltd. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <sys/socket.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <gatchat.h>
+#include <gatsyntax.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/call-barring.h>
+#include <ofono/call-forwarding.h>
+#include <ofono/call-meter.h>
+#include <ofono/call-settings.h>
+#include <ofono/devinfo.h>
+#include <ofono/message-waiting.h>
+#include <ofono/netreg.h>
+#include <ofono/phonebook.h>
+#include <ofono/sim.h>
+#include <ofono/sms.h>
+#include <ofono/ssn.h>
+#include <ofono/ussd.h>
+#include <ofono/voicecall.h>
+
+#define MODEM_DEVICE "/dev/smd0"
+
+static struct ofono_modem *g1_modem = NULL;
+
+struct g1_data {
+	GAtChat *chat;
+	GIOChannel *io;
+};
+
+static void connect_destroy(gpointer user)
+{
+	struct ofono_modem *modem = user;
+	struct g1_data *d = ofono_modem_get_data(modem);
+
+	d->io = NULL;
+}
+
+static void g1_debug(const char *str, void *data)
+{
+	DBG("%s", str);
+}
+
+static gboolean connect_cb(GIOChannel *io, GIOCondition cond, gpointer user)
+{
+	struct ofono_modem *modem = user;
+	struct g1_data *d = ofono_modem_get_data(modem);
+	int err = 0;
+	gboolean success;
+	GAtSyntax *syntax;
+
+	if (cond & G_IO_NVAL)
+		return FALSE;
+
+	if (cond & G_IO_OUT) {
+		int sock = g_io_channel_unix_get_fd(io);
+		socklen_t len = sizeof(err);
+
+		if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &len) < 0)
+			err = errno == ENOTSOCK ? 0 : errno;
+	} else if (cond & (G_IO_HUP | G_IO_ERR))
+		err = ECONNRESET;
+
+	success = !err;
+
+	DBG("io ref: %d", io->ref_count);
+
+	if (success == FALSE)
+		goto error;
+
+	syntax = g_at_syntax_new_gsmv1();
+	d->chat = g_at_chat_new(io, syntax);
+	g_at_syntax_unref(syntax);
+
+	DBG("io ref: %d", io->ref_count);
+
+	if (!d->chat)
+		goto error;
+
+	if (getenv("OFONO_AT_DEBUG") != NULL)
+		g_at_chat_set_debug(d->chat, g1_debug, NULL);
+
+	/* ensure modem is in a known state; verbose on, echo/quiet off */
+	g_at_chat_send(d->chat, "ATE0Q0V1", NULL, NULL, NULL, NULL);
+
+	/* power up modem */
+	g_at_chat_send(d->chat, "AT+CFUN=1", NULL, NULL, NULL, NULL);
+
+	ofono_modem_set_powered(modem, TRUE);
+
+	return FALSE;
+
+error:
+	ofono_modem_set_powered(modem, FALSE);
+	return FALSE;
+}
+
+static GIOChannel *tty_connect(const char *tty)
+{
+	GIOChannel *io;
+	int sk;
+	struct termios newtio;
+
+	sk = open(tty, O_RDWR | O_NOCTTY);
+
+	if (sk < 0) {
+		ofono_error("Can't open TTY %s: %s(%d)",
+				tty, strerror(errno), errno);
+		return NULL;
+	}
+
+	newtio.c_cflag = B115200 | CRTSCTS | CLOCAL | CREAD;
+	newtio.c_iflag = IGNPAR;
+	newtio.c_oflag = 0;
+	newtio.c_lflag = 0;
+
+	newtio.c_cc[VTIME] = 1;
+	newtio.c_cc[VMIN] = 5;
+
+	tcflush(sk, TCIFLUSH);
+	if (tcsetattr(sk, TCSANOW, &newtio) < 0) {
+		ofono_error("Can't change serial settings: %s(%d)",
+				strerror(errno), errno);
+		close(sk);
+		return NULL;
+	}
+
+	io = g_io_channel_unix_new(sk);
+	g_io_channel_set_close_on_unref(io, TRUE);
+
+	if (g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK,
+					NULL) != G_IO_STATUS_NORMAL) {
+		g_io_channel_unref(io);
+		return NULL;
+	}
+
+	return io;
+}
+
+static int g1_probe(struct ofono_modem *modem)
+{
+	struct g1_data *d;
+
+	d = g_new0(struct g1_data, 1);
+	if (!d)
+		return -ENOMEM;
+	ofono_modem_set_data(modem, d);
+
+	return 0;
+}
+
+static int g1_remove(struct ofono_modem *modem)
+{
+	g_free(ofono_modem_get_data(modem));
+
+	return 0;
+}
+
+static int g1_enable(struct ofono_modem *modem)
+{
+	struct g1_data *d = ofono_modem_get_data(modem);
+	GIOChannel *io;
+	GIOCondition cond;
+
+	DBG("");
+
+	io = tty_connect(MODEM_DEVICE);
+	if (io == NULL)
+		return -EINVAL;
+
+	DBG("io ref: %d", io->ref_count);
+
+	cond = G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
+	g_io_add_watch_full(io, G_PRIORITY_DEFAULT, cond, connect_cb,
+				modem, connect_destroy);
+
+	DBG("io ref: %d", io->ref_count);
+
+	g_io_channel_unref(io);
+
+	DBG("io ref: %d", io->ref_count);
+	d->io = io;
+
+	return -EINPROGRESS;
+}
+
+static int g1_disable(struct ofono_modem *modem)
+{
+	struct g1_data *d = ofono_modem_get_data(modem);
+
+	if (d->io) {
+		g_io_channel_close(d->io);
+		d->io = NULL;
+	}
+
+	if (d->chat) {
+		g_at_chat_unref(d->chat);
+		d->chat = NULL;
+	}
+
+	return 0;
+}
+
+static int g1_populate(struct ofono_modem *modem)
+{
+	struct g1_data *d = ofono_modem_get_data(modem);
+	GAtChat *chat = d->chat;
+	struct ofono_message_waiting *mw;
+
+	ofono_devinfo_create(modem, "generic_at", chat);
+	ofono_ussd_create(modem, "generic_at", chat);
+	ofono_sim_create(modem, "generic_at", chat);
+	ofono_call_forwarding_create(modem, "generic_at", chat);
+	ofono_call_settings_create(modem, "generic_at", chat);
+	ofono_netreg_create(modem, "generic_at", chat);
+	ofono_voicecall_create(modem, "generic_at", chat);
+	ofono_call_meter_create(modem, "generic_at", chat);
+	ofono_call_barring_create(modem, "generic_at", chat);
+	ofono_ssn_create(modem, "generic_at", chat);
+	ofono_sms_create(modem, "generic_at", chat);
+	ofono_phonebook_create(modem, "generic_at", chat);
+
+	mw = ofono_message_waiting_create(modem);
+	if (mw)
+		ofono_message_waiting_register(mw);
+
+	return 0;
+}
+
+static struct ofono_modem_driver g1_driver = {
+	.name = "HTC G1",
+	.probe = g1_probe,
+	.remove = g1_remove,
+	.enable = g1_enable,
+	.disable = g1_disable,
+	.populate = g1_populate,
+};
+
+static int g1_init(void)
+{
+	int err;
+
+	err = ofono_modem_driver_register(&g1_driver);
+	if (err)
+		goto done;
+
+	g1_modem = ofono_modem_create("G1", "HTC G1");
+	if (!g1_modem) {
+		err = -EIO;
+		goto unreg;
+	}
+
+	err = ofono_modem_register(g1_modem);
+	if (err)
+		goto remove;
+
+	return 0;
+
+remove:
+	ofono_modem_remove(g1_modem);
+unreg:
+	ofono_modem_driver_unregister(&g1_driver);
+done:
+	return err;
+}
+
+static void g1_exit(void)
+{
+	ofono_modem_remove(g1_modem);
+	ofono_modem_driver_unregister(&g1_driver);
+}
+
+OFONO_PLUGIN_DEFINE(g1, "HTC G1 modem driver", VERSION,
+			OFONO_PLUGIN_PRIORITY_DEFAULT,
+			g1_init, g1_exit)
-- 
1.6.3.3

             reply	other threads:[~2009-08-30  4:06 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-08-30  4:06 Andres Salomon [this message]
2009-09-01 17:13 ` [PATCH 1/3] G1: Add initial HTC G1 modem support Denis Kenzior

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=20090830040656.GA28039@mycelium.queued.net \
    --to=dilinger@collabora.co.uk \
    --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.