From 4e4d139e309c890b2c5c44b747aeaf9a5deac9bc Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Wed, 3 Apr 2013 12:24:18 +0200 Subject: 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. --- src/mm-serial-parsers.c | 36 ++++++++++++++++++++++++++++++++++-- src/mm-serial-parsers.h | 28 +++++++++++++++++++--------- 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 -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 */ -- cgit v1.2.3