android_adb_dbg: Add Android adb-debug backend

Add the adb-debug backend (identified by "qemud:adb-debug") which simply
prints all chars send accross the pipe buffers from the guest to stderr.

Reads are handled like the zero pipe.

Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 54a1f65..814a0f8 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -16,6 +16,7 @@
 
 obj-$(CONFIG_ANDROID_PIPE) += android_pipe.o
 obj-$(CONFIG_ANDROID_PIPE) += android_pipe_test.o
+obj-$(CONFIG_ANDROID_PIPE) += android_adb_dbg.o
 
 # PKUnity SoC devices
 common-obj-$(CONFIG_PUV3) += puv3_pm.o
diff --git a/hw/misc/android_adb_dbg.c b/hw/misc/android_adb_dbg.c
new file mode 100644
index 0000000..a3b1384
--- /dev/null
+++ b/hw/misc/android_adb_dbg.c
@@ -0,0 +1,145 @@
+/*
+ * ARM Android emulator adb backend
+ *
+ * Copyright (c) 2014 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Handle connections to the qemud:adb pipe from Android guests and route
+ * traffic over this pipe to the host adb server connecting to the qemu
+ * process on a tcp socket.
+ */
+
+#include "hw/misc/android_pipe.h"
+
+
+// #define DEBUG_ADB_DEBUG
+
+#ifdef DEBUG_ADB_DEBUG
+#define DPRINTF(fmt, ...) \
+do { fprintf(stderr, "adb_debug: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) do {} while(0)
+#endif
+
+static bool _pipe_backend_initialized = false;
+
+typedef struct {
+    void*     hwpipe;
+} adb_dbg_pipe;
+
+static void* adb_dbg_pipe_init(void *hwpipe,void *opaque, const char *args)
+{
+    adb_dbg_pipe *apipe;
+
+    DPRINTF("%s: hwpipe=%p", __FUNCTION__, hwpipe);
+    apipe = g_malloc0(sizeof(adb_dbg_pipe));
+    apipe->hwpipe = hwpipe;
+    return apipe;
+}
+
+static void adb_dbg_pipe_close(void *opaque)
+{
+    adb_dbg_pipe *apipe = opaque;
+
+    DPRINTF("%s: hwpipe=%p", __FUNCTION__, apipe->hwpipe);
+    g_free(apipe);
+}
+
+static unsigned pipe_buffers_len(const AndroidPipeBuffer *buffers, int cnt)
+{
+    unsigned len = 0;
+    while (cnt > 0) {
+        len += buffers[0].size;
+        cnt --;
+        buffers++;
+    }
+    return len;
+}
+
+/* Guest is sending us some ADB traces, print it on stderr */
+static int adb_dbg_pipe_send(void *opaque, const AndroidPipeBuffer *buffers,
+                             int cnt)
+{
+    int ret = 0;
+    char *data;
+    unsigned total_len = pipe_buffers_len(buffers, cnt);
+
+    DPRINTF("%s: something is coming over the wire....\n", __func__);
+
+    if (total_len > 4 * 4096) {
+        return total_len;  /* ignore outrageous requests */
+    }
+
+    data = g_malloc(total_len);
+
+    while (cnt > 0) {
+        memcpy(data, buffers[0].data, buffers[0].size);
+        data += buffers[0].size;
+        ret += buffers[0].size;
+
+        cnt--;
+        buffers++;
+    }
+
+    fprintf(stderr, "ADB: %s", data);
+
+    return ret;
+}
+
+/* Guest is reading data: Act as the zero pipe and just return a bunch of
+ * zeros.
+ */
+static int adb_dbg_pipe_recv(void *opaque, AndroidPipeBuffer *buffers,
+                             int cnt)
+{
+    int ret = 0;
+
+    while (cnt > 0) {
+        ret += buffers[0].size;
+        memset(buffers[0].data, 0, buffers[0].size);
+        buffers++;
+        cnt--;
+    }
+    return ret;
+}
+
+static unsigned adb_dbg_pipe_poll(void *opaque)
+{
+    return PIPE_POLL_IN | PIPE_POLL_OUT;
+}
+
+static void
+adb_dbg_pipe_wake_on(void *opaque, int flags)
+{
+    /* nothing to do here, we never block */
+}
+
+static const AndroidPipeFuncs adb_dbg_pipe_funcs = {
+    adb_dbg_pipe_init,
+    adb_dbg_pipe_close,
+    adb_dbg_pipe_send,
+    adb_dbg_pipe_recv,
+    adb_dbg_pipe_poll,
+    adb_dbg_pipe_wake_on,
+};
+
+void android_adb_dbg_backend_init(void)
+{
+    if (_pipe_backend_initialized) {
+        return;
+    }
+
+    android_pipe_add_type("qemud:adb-debug", NULL, &adb_dbg_pipe_funcs);
+    _pipe_backend_initialized = true;
+}
diff --git a/hw/misc/android_pipe.c b/hw/misc/android_pipe.c
index 5b44f0c..942ca376 100644
--- a/hw/misc/android_pipe.c
+++ b/hw/misc/android_pipe.c
@@ -788,6 +788,13 @@
     android_zero_pipe_init();
     android_pingpong_init();
     android_throttle_init();
+
+    /* TODO: This may be a complete hack and there may be beautiful QOM ways
+     * to accomplish this.
+     *
+     * Initialize android pipe backends
+     */
+    android_adb_dbg_backend_init();
 }
 
 void
diff --git a/include/hw/misc/android_pipe.h b/include/hw/misc/android_pipe.h
index 4db3731..3d1665c 100644
--- a/include/hw/misc/android_pipe.h
+++ b/include/hw/misc/android_pipe.h
@@ -220,5 +220,6 @@
 extern void android_zero_pipe_init(void);
 extern void android_pingpong_init(void);
 extern void android_throttle_init(void);
+extern void android_adb_dbg_backend_init(void);
 
 #endif /* _HW_ANDROID_PIPE_H */