blob: a3b13849c52e451bf1666bd85573041e6c21883f [file] [log] [blame] [edit]
/*
* 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;
}