Add GSM Permissive parser
authorDenis Kenzior <denis.kenzior@intel.com>
Fri, 4 Sep 2009 18:25:30 +0000 (13:25 -0500)
committerMarcel Holtmann <marcel@holtmann.org>
Sat, 5 Sep 2009 02:57:11 +0000 (04:57 +0200)
gatchat/gatsyntax.c
gatchat/gatsyntax.h

index d7c9ee2..a02f326 100644 (file)
@@ -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)
index 57edead..d0d9254 100644 (file)
@@ -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);