When debugging G1 stuff, it's really much more helpful to see exactly
what's going across the serial line.  A debug zone for the parser is
also useful, but that'll have to wait for denkenz's pluggable parser
stuff.



>From 4402edf0bd4c782229259e7ec17d6da5809d1deb Mon Sep 17 00:00:00 2001
From: Andres Salomon <dilin...@collabora.co.uk>
Date: Wed, 5 Aug 2009 17:18:34 -0400
Subject: [PATCH 2/2] atmodem: add serial line debugging to gatchat

This patch adds debugging support to GAtChat (specifically of what's going
across the serial line).  A callback is passed to g_at_chat_new*, and that
callback is called after any channel reads/writes.

>From the atmodem driver perspective, this adds an additional bit to the
debugging flags, and allows the user to select it via --debug=atio.
---
 drivers/atmodem/atmodem.c |   13 ++++++++++++-
 gatchat/gatchat.c         |   33 ++++++++++++++++++++++++++++++---
 gatchat/gatchat.h         |    7 +++++--
 include/log.h             |    5 +++++
 src/log.c                 |   39 +++++++++++++++++++++++++++++++++------
 src/main.c                |    1 +
 6 files changed, 86 insertions(+), 12 deletions(-)

diff --git a/drivers/atmodem/atmodem.c b/drivers/atmodem/atmodem.c
index fc255b3..56f5503 100644
--- a/drivers/atmodem/atmodem.c
+++ b/drivers/atmodem/atmodem.c
@@ -320,11 +320,21 @@ static void msg_destroy(gpointer user)
        dbus_message_unref(msg);
 }
 
+static void atmodem_debug(const char *format, ...)
+{
+       va_list ap;
+
+       va_start(ap, format);
+       __ofono_vdebug(OFONO_DEBUG_AT_IO, format, ap);
+       va_end(ap);
+}
+
 static void create_cb(GIOChannel *io, gboolean success, gpointer user)
 {
        DBusConnection *conn = ofono_dbus_get_connection();
        DBusMessage *msg = user;
        DBusMessage *reply;
+       GAtDebugFunc debugf;
        struct at_data *at = NULL;
        const char *path;
        const char *target, *driver;
@@ -337,7 +347,8 @@ static void create_cb(GIOChannel *io, gboolean success, 
gpointer user)
 
        at = g_new0(struct at_data, 1);
 
-       at->parser = g_at_chat_new(io, 0);
+       debugf = ofono_debug_flag_isset(OFONO_DEBUG_AT_IO) ? atmodem_debug : 
NULL; 
+       at->parser = g_at_chat_new(io, 0, debugf);
 
        if (!at->parser)
                goto out;
diff --git a/gatchat/gatchat.c b/gatchat/gatchat.c
index 15cc934..ff07136 100644
--- a/gatchat/gatchat.c
+++ b/gatchat/gatchat.c
@@ -96,6 +96,7 @@ struct _GAtChat {
        guint read_so_far;                      /* Number of bytes processed */
        gboolean disconnecting;                 /* Whether we're disconnecting 
*/
        enum chat_state state;          /* Current chat state */
+       GAtDebugFunc debugf;                    /* debugging output function */
        int flags;
        char *pdu_notify;                       /* Unsolicited Resp w/ PDU */
        GSList *response_lines;                 /* char * lines of the response 
*/
@@ -713,6 +714,27 @@ static void new_bytes(GAtChat *p)
        }
 }
 
+static void g_at_chat_debug_log(GAtChat *chat, gboolean is_read,
+               char *str, gsize len)
+{
+       char type = is_read ? '<' : '>';
+       char *tmp;
+
+       if (!chat->debugf || !len)
+               return;
+
+       if (len > 1024) {
+               /* let's keep it to a reasonable length.. */
+               chat->debugf("%c (ignoring string of length %d)\n", type, len);
+               return;
+       }
+
+       str[len] = '\0';        /* XXX: is it safe to overwrite this byte? */
+       tmp = g_strescape(str, "\"");
+       chat->debugf("%c %s\n", type, tmp);
+       g_free(tmp);
+}
+
 static gboolean received_data(GIOChannel *channel, GIOCondition cond,
                                gpointer data)
 {
@@ -747,6 +769,7 @@ static gboolean received_data(GIOChannel *channel, 
GIOCondition cond,
                buf = ring_buffer_write_ptr(chat->buf);
 
                err = g_io_channel_read(channel, (char *) buf, toread, &rbytes);
+               g_at_chat_debug_log(chat, TRUE, buf, rbytes);
 
                total_read += rbytes;
 
@@ -876,6 +899,8 @@ static gboolean can_write_data(GIOChannel *channel, 
GIOCondition cond,
                return FALSE;
        }
 
+       g_at_chat_debug_log(chat, FALSE, cmd->cmd + chat->cmd_bytes_written,
+                       bytes_written);
        chat->cmd_bytes_written += bytes_written;
 
        if (bytes_written < towrite)
@@ -900,7 +925,7 @@ static void g_at_chat_wakeup_writer(GAtChat *chat)
                                (GDestroyNotify)write_watcher_destroy_notify);
 }
 
-GAtChat *g_at_chat_new(GIOChannel *channel, int flags)
+GAtChat *g_at_chat_new(GIOChannel *channel, int flags, GAtDebugFunc debugf)
 {
        GAtChat *chat;
        GIOFlags io_flags;
@@ -915,6 +940,7 @@ GAtChat *g_at_chat_new(GIOChannel *channel, int flags)
 
        chat->next_cmd_id = 1;
        chat->next_notify_id = 1;
+       chat->debugf = debugf;
        chat->flags = flags;
 
        chat->buf = ring_buffer_new(4096);
@@ -1002,7 +1028,8 @@ static int open_device(const char *device)
        return fd;
 }
 
-GAtChat *g_at_chat_new_from_tty(const char *device, int flags)
+GAtChat *g_at_chat_new_from_tty(const char *device, int flags,
+               GAtDebugFunc debugf)
 {
        GIOChannel *channel;
        int fd;
@@ -1017,7 +1044,7 @@ GAtChat *g_at_chat_new_from_tty(const char *device, int 
flags)
                return NULL;
        }
 
-       return g_at_chat_new(channel, flags);
+       return g_at_chat_new(channel, flags, debugf);
 }
 
 GAtChat *g_at_chat_ref(GAtChat *chat)
diff --git a/gatchat/gatchat.h b/gatchat/gatchat.h
index 969f6f4..4353e08 100644
--- a/gatchat/gatchat.h
+++ b/gatchat/gatchat.h
@@ -36,6 +36,8 @@ typedef void (*GAtResultFunc)(gboolean success, GAtResult 
*result,
                                gpointer user_data);
 typedef void (*GAtNotifyFunc)(GAtResult *result, gpointer user_data);
 typedef void (*GAtDisconnectFunc)(gpointer user_data);
+typedef void (*GAtDebugFunc)(const char *format, ...)
+               __attribute__((format(printf, 1, 2)));
 
 enum _GAtChatFlags {
        G_AT_CHAT_FLAG_NO_LEADING_CRLF = 1,     /* Some emulators are broken */
@@ -44,8 +46,9 @@ enum _GAtChatFlags {
 
 typedef enum _GAtChatFlags GAtChatFlags;
 
-GAtChat *g_at_chat_new(GIOChannel *channel, int flags);
-GAtChat *g_at_chat_new_from_tty(const char *device, int flags);
+GAtChat *g_at_chat_new(GIOChannel *channel, int flags, GAtDebugFunc debugf);
+GAtChat *g_at_chat_new_from_tty(const char *device, int flags,
+               GAtDebugFunc debugf);
 
 int g_at_chat_get_flags(GAtChat *chat);
 void g_at_chat_set_flags(GAtChat *chat, int flags);
diff --git a/include/log.h b/include/log.h
index ef2c663..153308a 100644
--- a/include/log.h
+++ b/include/log.h
@@ -28,6 +28,7 @@ extern "C" {
 
 typedef enum {
        OFONO_DEBUG_CORE = 1 << 0,
+       OFONO_DEBUG_AT_IO = 1 << 1,
 } ofono_debug_flags;
 
 /**
@@ -42,9 +43,13 @@ extern void ofono_error(const char *format, ...)
                                __attribute__((format(printf, 1, 2)));
 extern void __ofono_debug(ofono_debug_flags flag, const char *format, ...)
                                __attribute__((format(printf, 2, 3)));
+extern void __ofono_vdebug(ofono_debug_flags flag, const char *format,
+                               va_list ap);
 #define ofono_debug(format, ...) \
                __ofono_debug(OFONO_DEBUG_CORE, (format), ##__VA_ARGS__)
 
+extern gboolean ofono_debug_flag_isset(ofono_debug_flags flag);
+
 /**
  * DBG:
  * @fmt: format string
diff --git a/src/log.c b/src/log.c
index 167fe21..c8c4d99 100644
--- a/src/log.c
+++ b/src/log.c
@@ -68,6 +68,38 @@ void ofono_error(const char *format, ...)
 }
 
 /**
+ * __ofono_vdebug:
+ * @flag: zone flag (ie, OFONO_DEBUG_CORE)
+ *
+ * Determine whether a specific debug flag is set or not
+ *
+ * Whether or not debugging is enabled is not considered.
+ */ 
+gboolean ofono_debug_flag_isset(ofono_debug_flags flag)
+{
+       return (debug_flags & flag) ? TRUE : FALSE;
+}
+
+/**
+ * __ofono_vdebug:
+ * @flag: zone flag (ie, OFONO_DEBUG_CORE)
+ * @format: format string
+ * @ap: valist of arguments
+ *
+ * Output debug message
+ *
+ * The actual output of the debug message is controlled via a command line
+ * switch. If not enabled, these messages will be ignored.
+ */
+void __ofono_vdebug(ofono_debug_flags flag, const char *format, va_list ap)
+{
+       if (!debug_enabled || !(debug_flags & flag))
+               return;
+
+       vsyslog(LOG_DEBUG, format, ap);
+}
+
+/**
  * __ofono_debug:
  * @flag: zone flag (ie, OFONO_DEBUG_CORE)
  * @format: format string
@@ -82,13 +114,8 @@ void __ofono_debug(ofono_debug_flags flag, const char 
*format, ...)
 {
        va_list ap;
 
-       if (!debug_enabled || !(debug_flags & flag))
-               return;
-
        va_start(ap, format);
-
-       vsyslog(LOG_DEBUG, format, ap);
-
+       __ofono_vdebug(flag, format, ap);
        va_end(ap);
 }
 
diff --git a/src/main.c b/src/main.c
index 7227bde..93f6f74 100644
--- a/src/main.c
+++ b/src/main.c
@@ -58,6 +58,7 @@ static guint debug_flags = 0;
 
 static GDebugKey keys[] = {
        { "core", OFONO_DEBUG_CORE },
+       { "atio", OFONO_DEBUG_AT_IO },
 };
 
 static gboolean parse_debug_flags(const gchar *option_name, const gchar *value,
-- 
1.6.3.3

_______________________________________________
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono

Reply via email to