summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Kenzior <denis.kenzior@intel.com>2009-09-04 13:25:30 -0500
committerMarcel Holtmann <marcel@holtmann.org>2009-09-05 04:57:11 +0200
commit044f24a4d7f6bc951836764512e4cc95c1f7635a (patch)
tree4143881e4ae5204a1a64ceeaf5810fff2f4c58eb
parenta7b632bd9e26fb0f580b7683700343e300da1680 (diff)
downloadconnman-044f24a4d7f6bc951836764512e4cc95c1f7635a.tar.gz
connman-044f24a4d7f6bc951836764512e4cc95c1f7635a.tar.bz2
connman-044f24a4d7f6bc951836764512e4cc95c1f7635a.zip
Add GSM Permissive parser
-rw-r--r--gatchat/gatsyntax.c89
-rw-r--r--gatchat/gatsyntax.h12
2 files changed, 100 insertions, 1 deletions
diff --git a/gatchat/gatsyntax.c b/gatchat/gatsyntax.c
index d7c9ee23..a02f326d 100644
--- a/gatchat/gatsyntax.c
+++ b/gatchat/gatsyntax.c
@@ -27,7 +27,7 @@
#include "gatsyntax.h"
-enum GSMV1_STATE_ {
+enum GSMV1_STATE {
GSMV1_STATE_IDLE = 0,
GSMV1_STATE_INITIAL_CR,
GSMV1_STATE_INITIAL_LF,
@@ -45,6 +45,14 @@ enum GSMV1_STATE_ {
GSMV1_STATE_GARBAGE_CHECK_LF,
};
+enum GSM_PERMISSIVE_STATE {
+ GSM_PERMISSIVE_STATE_IDLE = 0,
+ GSM_PERMISSIVE_STATE_RESPONSE,
+ GSM_PERMISSIVE_STATE_GUESS_PDU,
+ GSM_PERMISSIVE_STATE_PDU,
+ GSM_PERMISSIVE_STATE_PROMPT,
+};
+
static void gsmv1_hint(GAtSyntax *syntax, GAtSyntaxExpectHint hint)
{
switch (hint) {
@@ -215,6 +223,79 @@ out:
return res;
}
+static void gsm_permissive_hint(GAtSyntax *syntax, GAtSyntaxExpectHint hint)
+{
+ if (hint == G_AT_SYNTAX_EXPECT_PDU)
+ syntax->state = GSM_PERMISSIVE_STATE_GUESS_PDU;
+}
+
+static GAtSyntaxResult gsm_permissive_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 GSM_PERMISSIVE_STATE_IDLE:
+ if (byte == '\r' || byte == '\n')
+ /* ignore */;
+ else if (byte == '>')
+ syntax->state = GSM_PERMISSIVE_STATE_PROMPT;
+ else
+ syntax->state = GSM_PERMISSIVE_STATE_RESPONSE;
+ break;
+
+ case GSM_PERMISSIVE_STATE_RESPONSE:
+ if (byte == '\r') {
+ syntax->state = GSM_PERMISSIVE_STATE_IDLE;
+
+ i += 1;
+ res = G_AT_SYNTAX_RESULT_LINE;
+ goto out;
+ }
+ break;
+
+ case GSM_PERMISSIVE_STATE_GUESS_PDU:
+ if (byte != '\r' && byte != '\n')
+ syntax->state = GSM_PERMISSIVE_STATE_PDU;
+ break;
+
+ case GSM_PERMISSIVE_STATE_PDU:
+ if (byte == '\r') {
+ syntax->state = GSM_PERMISSIVE_STATE_IDLE;
+
+ i += 1;
+ res = G_AT_SYNTAX_RESULT_PDU;
+ goto out;
+ }
+ break;
+
+ case GSM_PERMISSIVE_STATE_PROMPT:
+ if (byte == ' ') {
+ syntax->state = GSM_PERMISSIVE_STATE_IDLE;
+ i += 1;
+ res = G_AT_SYNTAX_RESULT_PROMPT;
+ goto out;
+ }
+
+ syntax->state = GSM_PERMISSIVE_STATE_RESPONSE;
+ return G_AT_SYNTAX_RESULT_UNSURE;
+
+ default:
+ break;
+ };
+
+ i += 1;
+ }
+
+out:
+ *len = i;
+ return res;
+}
+
GAtSyntax *g_at_syntax_new_full(GAtSyntaxFeedFunc feed,
GAtSyntaxSetHintFunc hint,
int initial_state)
@@ -237,6 +318,12 @@ GAtSyntax *g_at_syntax_new_gsmv1()
return g_at_syntax_new_full(gsmv1_feed, gsmv1_hint, GSMV1_STATE_IDLE);
}
+GAtSyntax *g_at_syntax_new_gsm_permissive()
+{
+ return g_at_syntax_new_full(gsm_permissive_feed, gsm_permissive_hint,
+ GSM_PERMISSIVE_STATE_IDLE);
+}
+
GAtSyntax *g_at_syntax_ref(GAtSyntax *syntax)
{
if (syntax == NULL)
diff --git a/gatchat/gatsyntax.h b/gatchat/gatsyntax.h
index 57edeade..d0d9254b 100644
--- a/gatchat/gatsyntax.h
+++ b/gatchat/gatsyntax.h
@@ -63,8 +63,20 @@ struct _GAtSyntax {
GAtSyntax *g_at_syntax_new_full(GAtSyntaxFeedFunc feed,
GAtSyntaxSetHintFunc hint,
int initial_state);
+
+/* This syntax implements very strict checking of 27.007 standard, which means
+ * it might not work with a majority of modems. However, it does handle echo
+ * properly and can be used to detect a modem's deviations from the relevant
+ * standards.
+ */
GAtSyntax *g_at_syntax_new_gsmv1();
+/* This syntax implements an extremely lax parser that can handle a variety
+ * of modems. Unfortunately it does not deal with echo at all, so echo must
+ * be explicitly turned off before using the parser
+ */
+GAtSyntax *g_at_syntax_new_gsm_permissive();
+
GAtSyntax *g_at_syntax_ref(GAtSyntax *syntax);
void g_at_syntax_unref(GAtSyntax *syntax);