Skip to contentSkip to conversation

G1: Add initial HTC G1 modem support

PATCH In review Andres Salomon 2 participants 2 messages Aug 30, 2009 – Sep 1, 2009 Kbuild

lore
Share & tools
lore
#0 lore raw

PATCH 1/3 G1: Add initial HTC G1 modem support

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
Makefile.am +5 -0
index 7ee6536..a2d3569 100644
@@ -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
configure.ac +7 -1
index a299a13..5deabb8 100644
@@ -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))
plugins/g1.c new file +309 -0

309 lines not on this page · raw message

Signature · 1 line
1.6.3.3
#1 lore raw

Hi Andres,

Quoted 34 lines

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.
+static gboolean connect_cb(GIOChannel *io, GIOCondition cond, gpointer user) +{

plugins/g1.c new file +24 -0
+	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;

plugins/g1.c line 113

Quoted 10 lines
plugins/g1.c new file +10 -0
+
+	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;
+

Since this is a tty, you probably don't need this function at all.

Quoted 31 lines
plugins/g1.c new file +31 -0
+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);

plugins/g1.c line 172

Quoted 10 lines
plugins/g1.c new file +10 -0
+	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;
+}

You might want to see if using g_at_chat_new_from_tty works here. If not, then the opening the tty should be broken out into a separate utility function that can be used from multiple drivers.

Quoted 17 lines
plugins/g1.c new file +17 -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);

plugins/g1.c line 219

Quoted 10 lines
plugins/g1.c new file +10 -0
+
+	DBG("io ref: %d", io->ref_count);
+
+	g_io_channel_unref(io);
+
+	DBG("io ref: %d", io->ref_count);
+	d->io = io;
+
+	return -EINPROGRESS;
+}

So I know the generic_at driver does this, but in a real device driver this is wrong. You should probably be using AT+CFUN=1 here. If the g1 supports even more drastic power up/down options, then these should be used.

Quoted 7 lines
plugins/g1.c new file +7 -0
+
+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);

plugins/g1.c line 236

Quoted 10 lines
plugins/g1.c new file +10 -0
+		d->io = NULL;
+	}
+
+	if (d->chat) {
+		g_at_chat_unref(d->chat);
+		d->chat = NULL;
+	}
+
+	return 0;
+}

Same thing here. AT+CFUN=0 or AT+CFUN=4.

Quoted 18 lines
plugins/g1.c new file +18 -0
+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;
+

plugins/g1.c line 300

Quoted 10 lines
plugins/g1.c new file +10 -0
+	return 0;
+
+remove:
+	ofono_modem_remove(g1_modem);
+unreg:
+	ofono_modem_driver_unregister(&g1_driver);
+done:
+	return err;
+}
+

I'd really like to see some sort of detection mechanism here. Even if it is a basic 'if exists /dev/smd0' or reading something from /proc. As I don't necessarily want to see the g1 showing up everywhere.

Regads,
-Denis