summaryrefslogtreecommitdiffstats
path: root/plugins/g1.c
diff options
context:
space:
mode:
authorAndres Salomon <dilinger@collabora.co.uk>2009-08-25 18:07:28 -0400
committerMarcel Holtmann <marcel@holtmann.org>2009-09-02 16:11:10 -0700
commit3b1733b18af596b0085902986eafd646ab08c58d (patch)
tree7422604dc4997f34a9a59e3a0f6b78b7735addc9 /plugins/g1.c
parent7b9f0773fa0bee12b9fe3128ad424f14ece731f0 (diff)
downloadofono-3b1733b18af596b0085902986eafd646ab08c58d.tar.bz2
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.
Diffstat (limited to 'plugins/g1.c')
-rw-r--r--plugins/g1.c87
1 files changed, 85 insertions, 2 deletions
diff --git a/plugins/g1.c b/plugins/g1.c
index ab88e1cb..30b9f949 100644
--- a/plugins/g1.c
+++ b/plugins/g1.c
@@ -28,7 +28,6 @@
#include <glib.h>
#include <gatchat.h>
-#include <gatsyntax.h>
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/plugin.h>
@@ -48,6 +47,90 @@
#include <ofono/ussd.h>
#include <ofono/voicecall.h>
+/* 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 g1_debug(const char *str, void *data)
{
DBG("%s", str);
@@ -61,7 +144,7 @@ static int g1_probe(struct ofono_modem *modem)
DBG("");
- syntax = g_at_syntax_new_gsmv1();
+ syntax = g_at_syntax_new_full(g1_feed, g1_hint, G1_STATE_IDLE);
chat = g_at_chat_new_from_tty("/dev/smd0", syntax);
g_at_syntax_unref(syntax);