aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2013-04-03 12:24:18 +0200
committerAleksander Morgado <aleksander@lanedo.com>2013-04-04 19:26:51 +0200
commit4e4d139e309c890b2c5c44b747aeaf9a5deac9bc (patch)
tree5c8b1edfd18a514946cc9ed2213641f25b601c8e
parent38b120c8617724ba97ac212c9e01d01c850abdc8 (diff)
serial-parsers: allow specifying a custom response filter
The serial parser will now allow specifying a custom user-provided filter, which is applied before even trying to match successful/error responses. This filter provides a very early barrier to detect strings that are clearly not going to match. E.g. this filter may be used during port probing to early detect non-AT ports.
-rw-r--r--src/mm-serial-parsers.c36
-rw-r--r--src/mm-serial-parsers.h28
2 files changed, 53 insertions, 11 deletions
diff --git a/src/mm-serial-parsers.c b/src/mm-serial-parsers.c
index 53b22a81..a267d046 100644
--- a/src/mm-serial-parsers.c
+++ b/src/mm-serial-parsers.c
@@ -94,6 +94,9 @@ typedef struct {
GRegex *regex_unknown_error;
GRegex *regex_connect_failed;
GRegex *regex_custom_error;
+ /* User-provided parser filter */
+ mm_serial_parser_v1_filter_fn filter_callback;
+ gpointer filter_user_data;
} MMSerialParserV1;
gpointer
@@ -117,6 +120,8 @@ mm_serial_parser_v1_new (void)
parser->regex_custom_successful = NULL;
parser->regex_custom_error = NULL;
+ parser->filter_callback = NULL;
+ parser->filter_user_data = NULL;
return parser;
}
@@ -139,6 +144,19 @@ mm_serial_parser_v1_set_custom_regex (gpointer data,
parser->regex_custom_error = error ? g_regex_ref (error) : NULL;
}
+void
+mm_serial_parser_v1_add_filter (gpointer data,
+ mm_serial_parser_v1_filter_fn callback,
+ gpointer user_data)
+{
+ MMSerialParserV1 *parser = (MMSerialParserV1 *) data;
+
+ g_return_if_fail (parser != NULL);
+
+ parser->filter_callback = callback;
+ parser->filter_user_data = user_data;
+}
+
gboolean
mm_serial_parser_v1_parse (gpointer data,
GString *response,
@@ -160,7 +178,20 @@ mm_serial_parser_v1_parse (gpointer data,
if (G_UNLIKELY (!response->len))
return FALSE;
- /* First, check for successful responses */
+ /* First, apply custom filter if any */
+ if (parser->filter_callback &&
+ !parser->filter_callback (parser,
+ parser->filter_user_data,
+ response,
+ &local_error)) {
+ g_assert (local_error != NULL);
+ mm_dbg ("Got response filtered in serial port: %s", local_error->message);
+ g_propagate_error (error, local_error);
+ response_clean (response);
+ return TRUE;
+ }
+
+ /* Then, check for successful responses */
/* Custom successful replies first, if any */
if (parser->regex_custom_successful) {
@@ -326,7 +357,8 @@ mm_serial_parser_v1_is_known_error (const GError *error)
/* Need to return TRUE for the kind of errors that this parser may set */
return (error->domain == MM_MOBILE_EQUIPMENT_ERROR ||
error->domain == MM_CONNECTION_ERROR ||
- error->domain == MM_MESSAGE_ERROR);
+ error->domain == MM_MESSAGE_ERROR ||
+ g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_PARSE_FAILED));
}
void
diff --git a/src/mm-serial-parsers.h b/src/mm-serial-parsers.h
index 81e7a2d0..641c5e0f 100644
--- a/src/mm-serial-parsers.h
+++ b/src/mm-serial-parsers.h
@@ -18,14 +18,24 @@
#include <glib.h>
-gpointer mm_serial_parser_v1_new (void);
-void mm_serial_parser_v1_set_custom_regex (gpointer data,
- GRegex *successful,
- GRegex *error);
-gboolean mm_serial_parser_v1_parse (gpointer parser,
- GString *response,
- GError **error);
-void mm_serial_parser_v1_destroy (gpointer parser);
-gboolean mm_serial_parser_v1_is_known_error (const GError *error);
+gpointer mm_serial_parser_v1_new (void);
+void mm_serial_parser_v1_set_custom_regex (gpointer data,
+ GRegex *successful,
+ GRegex *error);
+gboolean mm_serial_parser_v1_parse (gpointer parser,
+ GString *response,
+ GError **error);
+void mm_serial_parser_v1_destroy (gpointer parser);
+gboolean mm_serial_parser_v1_is_known_error (const GError *error);
+
+/* Parser filter: when FALSE returned, error should be set. This error will be
+ * reported to the response listener right away. */
+typedef gboolean (* mm_serial_parser_v1_filter_fn) (gpointer data,
+ gpointer user_data,
+ GString *response,
+ GError **error);
+void mm_serial_parser_v1_add_filter (gpointer data,
+ mm_serial_parser_v1_filter_fn callback,
+ gpointer user_data);
#endif /* MM_SERIAL_PARSERS_H */