diff options
author | Andres Salomon <dilinger@collabora.co.uk> | 2009-08-25 18:07:28 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2009-09-02 16:11:10 -0700 |
commit | 3b1733b18af596b0085902986eafd646ab08c58d (patch) | |
tree | 7422604dc4997f34a9a59e3a0f6b78b7735addc9 /plugins/g1.c | |
parent | 7b9f0773fa0bee12b9fe3128ad424f14ece731f0 (diff) | |
download | ofono-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.c | 87 |
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); |