Skip to contentSkip to conversation

G1: Add a G1 syntax for parsing

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

lore
Share & tools
lore
#0 lore raw

PATCH 2/3 G1: Add a G1 syntax for parsing

This is based on the generic_at parser, with unnecessary stuff removed.

The G1 routinely screws up CRLFs, so the parser needs to account for that. This parser ignores leading CRLFs (which is what reference-ril does as well), as well as trailing LFs (which are sometimes left out). CRs are used as end-of-message indicators. Since we're not bothering tracking CRLFs, there's also no need for a GARBAGE state, or MULTILINE stuff.

---
 plugins/g1.c |   87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 85 insertions(+), 2 deletions(-)
plugins/g1.c +85 -2
index 70e4914..b0208bc 100644
@@ -33,7 +33,6 @@
 
 #include <glib.h>
 #include <gatchat.h>
-#include <gatsyntax.h>
 
 #define OFONO_API_SUBJECT_TO_CHANGE
 #include <ofono/plugin.h>
@@ -62,6 +61,90 @@ struct g1_data {
 	GIOChannel *io;
 };
 
+/* Supply our own syntax parser */
+
+enum G1_STATE_ {
+	G1_STATE_IDLE = 0,
+	G1_STATE_RESPONSE,
+	G1_STATE_GUESS_PDU,
+	G1_STATE_PDU,
+	G1_STATE_PROMPT,
+};
+
+static void g1_hint(GAtSyntax *syntax, GAtSyntaxExpectHint hint)
+{
+	if (hint == G_AT_SYNTAX_EXPECT_PDU)
+		syntax->state = G1_STATE_GUESS_PDU;
+}
+
+static GAtSyntaxResult g1_feed(GAtSyntax *syntax,
+		const char *bytes, gsize *len)
+{
+	gsize i = 0;
+	GAtSyntaxResult res = G_AT_SYNTAX_RESULT_UNSURE;
+
+	while (i < *len) {
+		char byte = bytes[i];
+
+		switch (syntax->state) {
+		case G1_STATE_IDLE:
+			if (byte == '\r' || byte == '\n')
+				/* ignore */;
+			else if (byte == '>')
+				syntax->state = G1_STATE_PROMPT;
+			else
+				syntax->state = G1_STATE_RESPONSE;
+			break;
+
+		case G1_STATE_RESPONSE:
+			if (byte == '\r') {
+				syntax->state = G1_STATE_IDLE;
+
+				i += 1;
+				res = G_AT_SYNTAX_RESULT_LINE;
+				goto out;
+			}
+			break;
+
+		case G1_STATE_GUESS_PDU:
+			/* keep going until we find a LF that leads the PDU */
+			if (byte == '\n')
+				syntax->state = G1_STATE_PDU;
+			break;
+
+		case G1_STATE_PDU:
+			if (byte == '\r') {
+				syntax->state = G1_STATE_IDLE;
+
+				i += 1;
+				res = G_AT_SYNTAX_RESULT_PDU;
+				goto out;
+			}
+			break;
+
+		case G1_STATE_PROMPT:
+			if (byte == ' ') {
+				syntax->state = G1_STATE_IDLE;
+				i += 1;
+				res = G_AT_SYNTAX_RESULT_PROMPT;
+				goto out;
+			}
+
+			syntax->state = G1_STATE_RESPONSE;
+			return G_AT_SYNTAX_RESULT_UNSURE;
+
+		default:
+			break;
+		};
+
+		i += 1;
+	}
+
+out:
+	*len = i;
+	return res;
+}
+
 static void connect_destroy(gpointer user)
 {
 	struct ofono_modem *modem = user;
@@ -102,7 +185,7 @@ static gboolean connect_cb(GIOChannel *io, GIOCondition cond, gpointer user)
 	if (success == FALSE)
 		goto error;
 
-	syntax = g_at_syntax_new_gsmv1();
+	syntax = g_at_syntax_new_full(g1_feed, g1_hint, G1_STATE_IDLE);
 	d->chat = g_at_chat_new(io, syntax);
 	g_at_syntax_unref(syntax);
 
Signature · 1 line
1.6.3.3
#1 lore raw

Hi Andres,

Quoted 9 lines

This is based on the generic_at parser, with unnecessary stuff removed.

The G1 routinely screws up CRLFs, so the parser needs to account for that. This parser ignores leading CRLFs (which is what reference-ril does as well), as well as trailing LFs (which are sometimes left out). CRs are used as end-of-message indicators. Since we're not bothering tracking CRLFs, there's also no need for a GARBAGE state, or MULTILINE stuff.
---

This one looks fine to me.

Regards,
-Denis