aboutsummaryrefslogtreecommitdiffstats
path: root/charpipe.c
diff options
context:
space:
mode:
authorDavid Turner <>2009-04-05 14:23:06 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2009-04-05 14:23:06 -0700
commit4735694ff99078f961876525ebbd55317956083f (patch)
tree0d6058c84618d7b2b30ef2b6a7d105f11dc01802 /charpipe.c
parente8b10bc4023bf84dcdb11940bbad9baf81bdd02c (diff)
downloadexternal_qemu-4735694ff99078f961876525ebbd55317956083f.zip
external_qemu-4735694ff99078f961876525ebbd55317956083f.tar.gz
external_qemu-4735694ff99078f961876525ebbd55317956083f.tar.bz2
AI 144597: am: CL 144596 am: CL 144595 Fix the AVD configuration code to support "sdcard.path" in config.ini to indicate an explicit SD Card image file (instead of using the one in the content directory)
Note that this also fix a bug where the SD Card image was not properly locked in the previous implementation. Allow the http-proxy support code to actually manage to receive chunked encoding data, instead of complaining needlessly. Introduce a new CharBuffer object that is used indirectly by "-radio <hostdevice>" and "-gps <hostdevice>" options Add new documentation for QEMUD and CharDriverState objects Update the Audio documentation with ASCII graphics (because I'm an artist too) Original author: digit Merged from: //branches/cupcake/... Original author: android-build Automated import of CL 144597
Diffstat (limited to 'charpipe.c')
-rw-r--r--charpipe.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/charpipe.c b/charpipe.c
index d6b9829..992b45a 100644
--- a/charpipe.c
+++ b/charpipe.c
@@ -253,12 +253,202 @@ qemu_chr_open_charpipe( CharDriverState* *pfirst, CharDriverState* *psecond )
return 0;
}
+/** This models a charbuffer, an object used to buffer
+ ** the data that is sent to a given endpoint CharDriverState
+ ** object.
+ **
+ ** On the other hand, any can_read() / read() request performed
+ ** by the endpoint will be passed to the CharBuffer's corresponding
+ ** handlers.
+ **/
+
+typedef struct CharBuffer {
+ CharDriverState cs[1];
+ BipBuffer* bip_first;
+ BipBuffer* bip_last;
+ CharDriverState* endpoint; /* NULL if closed */
+ char closing;
+} CharBuffer;
+
+
+static void
+charbuffer_close( CharDriverState* cs )
+{
+ CharBuffer* cbuf = cs->opaque;
+
+ while (cbuf->bip_first) {
+ BipBuffer* bip = cbuf->bip_first;
+ cbuf->bip_first = bip->next;
+ bip_buffer_free(bip);
+ }
+ cbuf->bip_last = NULL;
+ cbuf->endpoint = NULL;
+
+ if (cbuf->endpoint != NULL) {
+ qemu_chr_close(cbuf->endpoint);
+ cbuf->endpoint = NULL;
+ }
+}
+
+static int
+charbuffer_write( CharDriverState* cs, const uint8_t* buf, int len )
+{
+ CharBuffer* cbuf = cs->opaque;
+ CharDriverState* peer = cbuf->endpoint;
+ BipBuffer* bip = cbuf->bip_last;
+ int ret = 0;
+
+ D("%s: writing %d bytes to %p: '%s'", __FUNCTION__,
+ len, cbuf, quote_bytes( buf, len ));
+
+ if (bip == NULL && peer != NULL) {
+ /* no buffered data, try to write directly to the peer */
+ int size = qemu_chr_write(peer, buf, len);
+
+ if (size < 0) /* just to be safe */
+ size = 0;
+ else if (size > len)
+ size = len;
+
+ buf += size;
+ ret += size;
+ len -= size;
+ }
+
+ if (len == 0)
+ return ret;
+
+ /* buffer the remaining data */
+ if (bip == NULL) {
+ bip = bip_buffer_alloc();
+ cbuf->bip_first = cbuf->bip_last = bip;
+ }
+
+ while (len > 0) {
+ int len2 = cbuffer_write( bip->cb, buf, len );
+
+ buf += len2;
+ ret += len2;
+ len -= len2;
+ if (len == 0)
+ break;
+
+ /* ok, we need another buffer */
+ cbuf->bip_last = bip_buffer_alloc();
+ bip->next = cbuf->bip_last;
+ bip = cbuf->bip_last;
+ }
+ return ret;
+}
+
+
+static void
+charbuffer_poll( CharBuffer* cbuf )
+{
+ CharDriverState* peer = cbuf->endpoint;
+
+ if (peer == NULL)
+ return;
+
+ while (1) {
+ BipBuffer* bip = cbuf->bip_first;
+ uint8_t* base;
+ int avail;
+ int size;
+
+ if (bip == NULL)
+ break;
+
+ avail = cbuffer_read_peek( bip->cb, &base );
+ if (avail == 0) {
+ cbuf->bip_first = bip->next;
+ if (cbuf->bip_first == NULL)
+ cbuf->bip_last = NULL;
+ bip_buffer_free(bip);
+ continue;
+ }
+
+ size = qemu_chr_write( peer, base, avail );
+
+ if (size < 0) /* just to be safe */
+ size = 0;
+ else if (size > avail)
+ size = avail;
+
+ cbuffer_read_step( bip->cb, size );
+
+ if (size < avail)
+ break;
+ }
+}
+
+
+static void
+charbuffer_update_handlers( CharDriverState* cs )
+{
+ CharBuffer* cbuf = cs->opaque;
+
+ qemu_chr_add_handlers( cbuf->endpoint,
+ cs->chr_can_read,
+ cs->chr_read,
+ cs->chr_event,
+ cs->handler_opaque );
+}
+
+
+static void
+charbuffer_init( CharBuffer* cbuf, CharDriverState* endpoint )
+{
+ CharDriverState* cs = cbuf->cs;
+
+ cbuf->bip_first = NULL;
+ cbuf->bip_last = NULL;
+ cbuf->endpoint = endpoint;
+
+ cs->chr_write = charbuffer_write;
+ cs->chr_ioctl = NULL;
+ cs->chr_send_event = NULL;
+ cs->chr_close = charbuffer_close;
+ cs->chr_update_read_handler = charbuffer_update_handlers;
+ cs->opaque = cbuf;
+}
+
+#define MAX_CHAR_BUFFERS 8
+
+static CharBuffer _s_charbuffers[ MAX_CHAR_BUFFERS ];
+
+CharDriverState*
+qemu_chr_open_buffer( CharDriverState* endpoint )
+{
+ CharBuffer* cbuf = _s_charbuffers;
+ CharBuffer* cbuf_end = cbuf + MAX_CHAR_BUFFERS;
+
+ if (endpoint == NULL)
+ return NULL;
+
+ for ( ; cbuf < cbuf_end; cbuf++ ) {
+ if (cbuf->endpoint == NULL)
+ break;
+ }
+
+ if (cbuf == cbuf_end)
+ return NULL;
+
+ charbuffer_init(cbuf, endpoint);
+ return cbuf->cs;
+}
+
+
void
charpipe_poll( void )
{
CharPipeState* cp = _s_charpipes;
CharPipeState* cp_end = cp + MAX_CHAR_PIPES;
+ CharBuffer* cb = _s_charbuffers;
+ CharBuffer* cb_end = cb + MAX_CHAR_BUFFERS;
+
+ /* poll the charpipes */
for ( ; cp < cp_end; cp++ ) {
CharPipeHalf* half;
@@ -270,4 +460,10 @@ charpipe_poll( void )
if (half->peer != NULL)
charpipehalf_poll(half);
}
+
+ /* poll the charbuffers */
+ for ( ; cb < cb_end; cb++ ) {
+ if (cb->endpoint != NULL)
+ charbuffer_poll(cb);
+ }
}