aboutsummaryrefslogtreecommitdiff
path: root/src/mm-serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mm-serial.c')
-rw-r--r--src/mm-serial.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/src/mm-serial.c b/src/mm-serial.c
index c81ca70d..3bd2b0d6 100644
--- a/src/mm-serial.c
+++ b/src/mm-serial.c
@@ -49,6 +49,7 @@ typedef struct {
MMSerialResponseParserFn response_parser_fn;
gpointer response_parser_user_data;
GDestroyNotify response_parser_notify;
+ GSList *unsolicited_msg_handlers;
struct termios old_t;
@@ -65,6 +66,13 @@ typedef struct {
guint timeout_id;
} MMSerialPrivate;
+typedef struct {
+ GRegex *regex;
+ MMSerialUnsolicitedMsgFn callback;
+ gpointer user_data;
+ GDestroyNotify notify;
+} MMUnsolicitedMsgHandler;
+
const char *
mm_serial_get_device (MMSerial *serial)
{
@@ -436,6 +444,29 @@ mm_serial_queue_process (gpointer data)
}
void
+mm_serial_add_unsolicited_msg_handler (MMSerial *self,
+ GRegex *regex,
+ MMSerialUnsolicitedMsgFn callback,
+ gpointer user_data,
+ GDestroyNotify notify)
+{
+ MMUnsolicitedMsgHandler *handler;
+ MMSerialPrivate *priv;
+
+ g_return_if_fail (MM_IS_SERIAL (self));
+ g_return_if_fail (regex != NULL);
+
+ handler = g_slice_new (MMUnsolicitedMsgHandler);
+ handler->regex = g_regex_ref (regex);
+ handler->callback = callback;
+ handler->user_data = user_data;
+ handler->notify = notify;
+
+ priv = MM_SERIAL_GET_PRIVATE (self);
+ priv->unsolicited_msg_handlers = g_slist_append (priv->unsolicited_msg_handlers, handler);
+}
+
+void
mm_serial_set_response_parser (MMSerial *self,
MMSerialResponseParserFn fn,
gpointer user_data,
@@ -454,6 +485,58 @@ mm_serial_set_response_parser (MMSerial *self,
}
static gboolean
+remove_eval_cb (const GMatchInfo *match_info,
+ GString *result,
+ gpointer user_data)
+{
+ int *result_len = (int *) user_data;
+ int start;
+ int end;
+
+ if (g_match_info_fetch_pos (match_info, 0, &start, &end))
+ *result_len -= (end - start);
+
+ return FALSE;
+}
+
+static void
+parse_unsolicited_messages (MMSerial *self,
+ GString *response)
+{
+ MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self);
+ GSList *iter;
+
+ for (iter = priv->unsolicited_msg_handlers; iter; iter = iter->next) {
+ MMUnsolicitedMsgHandler *handler = (MMUnsolicitedMsgHandler *) iter->data;
+ GMatchInfo *match_info;
+ gboolean matches;
+
+ matches = g_regex_match_full (handler->regex, response->str, response->len, 0, 0, &match_info, NULL);
+ if (handler->callback) {
+ while (g_match_info_matches (match_info)) {
+ handler->callback (self, match_info, handler->user_data);
+ g_match_info_next (match_info, NULL);
+ }
+ }
+
+ g_match_info_free (match_info);
+
+ if (matches) {
+ /* Remove matches */
+ char *str;
+ int result_len = response->len;
+
+ str = g_regex_replace_eval (handler->regex, response->str, response->len, 0, 0,
+ remove_eval_cb, &result_len, NULL);
+
+ g_string_truncate (response, 0);
+ g_string_append_len (response, str, result_len);
+ g_free (str);
+ }
+ }
+}
+
+static gboolean
parse_response (MMSerial *self,
GString *response,
GError **error)
@@ -462,6 +545,8 @@ parse_response (MMSerial *self,
g_return_val_if_fail (priv->response_parser_fn != NULL, FALSE);
+ parse_unsolicited_messages (self, response);
+
return priv->response_parser_fn (priv->response_parser_user_data, response, error);
}
@@ -841,6 +926,18 @@ finalize (GObject *object)
g_string_free (priv->response, TRUE);
g_free (priv->device);
+ while (priv->unsolicited_msg_handlers) {
+ MMUnsolicitedMsgHandler *handler = (MMUnsolicitedMsgHandler *) priv->unsolicited_msg_handlers->data;
+
+ if (handler->notify)
+ handler->notify (handler->user_data);
+
+ g_regex_unref (handler->regex);
+ g_slice_free (MMUnsolicitedMsgHandler, handler);
+ priv->unsolicited_msg_handlers = g_slist_delete_link (priv->unsolicited_msg_handlers,
+ priv->unsolicited_msg_handlers);
+ }
+
if (priv->response_parser_notify)
priv->response_parser_notify (priv->response_parser_user_data);