static int charpipehalf_write( CharDriverState* cs, const uint8_t* buf, int len ) { CharPipeHalf* ph = cs->opaque; CharPipeHalf* peer = ph->peer; BipBuffer* bip = ph->bip_last; int ret = 0; D("%s: writing %d bytes to %p: '%s'", __FUNCTION__, len, ph, quote_bytes( buf, len )); if (bip == NULL && peer != NULL && peer->cs->chr_read != NULL) { /* no buffered data, try to write directly to the peer */ while (len > 0) { int size; if (peer->cs->chr_can_read) { size = qemu_chr_can_read( peer->cs ); if (size == 0) break; if (size > len) size = len; } else size = len; qemu_chr_read( peer->cs, (uint8_t*)buf, size ); buf += size; len -= size; ret += size; } } if (len == 0) return ret; /* buffer the remaining data */ if (bip == NULL) { bip = bip_buffer_alloc(); ph->bip_first = ph->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 */ ph->bip_last = bip_buffer_alloc(); bip->next = ph->bip_last; bip = ph->bip_last; } return ret; }
static void charpipehalf_poll( CharPipeHalf* ph ) { CharPipeHalf* peer = ph->peer; int size; if (peer == NULL || peer->cs->chr_read == NULL) return; while (1) { BipBuffer* bip = ph->bip_first; uint8_t* base; int avail; if (bip == NULL) break; size = cbuffer_read_avail(bip->cb); if (size == 0) { ph->bip_first = bip->next; if (ph->bip_first == NULL) ph->bip_last = NULL; bip_buffer_free(bip); continue; } if (ph->cs->chr_can_read) { int size2 = qemu_chr_can_read(peer->cs); if (size2 == 0) break; if (size > size2) size = size2; } avail = cbuffer_read_peek( bip->cb, &base ); if (avail > size) avail = size; D("%s: sending %d bytes from %p: '%s'", __FUNCTION__, avail, ph, quote_bytes( base, avail )); qemu_chr_read( peer->cs, base, avail ); cbuffer_read_step( bip->cb, avail ); } }
/* We want to send a packet */ static void baum_write_packet(BaumDriverState *baum, const uint8_t *buf, int len) { uint8_t io_buf[1 + 2 * len], *cur = io_buf; int room; *cur++ = ESC; while (len--) if ((*cur++ = *buf++) == ESC) *cur++ = ESC; room = qemu_chr_can_read(baum->chr); len = cur - io_buf; if (len <= room) { /* Fits */ qemu_chr_read(baum->chr, io_buf, len); } else { int first; uint8_t out; /* Can't fit all, send what can be, and store the rest. */ qemu_chr_read(baum->chr, io_buf, room); len -= room; cur = io_buf + room; if (len > BUF_SIZE - baum->out_buf_used) { /* Can't even store it, drop the previous data... */ assert(len <= BUF_SIZE); baum->out_buf_used = 0; baum->out_buf_ptr = 0; } out = baum->out_buf_ptr; baum->out_buf_used += len; first = BUF_SIZE - baum->out_buf_ptr; if (len > first) { memcpy(baum->out_buf + out, cur, first); out = 0; len -= first; cur += first; } memcpy(baum->out_buf + out, cur, len); } }
/* The serial port can receive more of our data */ static void baum_accept_input(struct CharDriverState *chr) { BaumDriverState *baum = chr->opaque; int room, first; if (!baum->out_buf_used) return; room = qemu_chr_can_read(chr); if (!room) return; if (room > baum->out_buf_used) room = baum->out_buf_used; first = BUF_SIZE - baum->out_buf_ptr; if (room > first) { qemu_chr_read(chr, baum->out_buf + baum->out_buf_ptr, first); baum->out_buf_ptr = 0; baum->out_buf_used -= first; room -= first; } qemu_chr_read(chr, baum->out_buf + baum->out_buf_ptr, room); baum->out_buf_ptr += room; baum->out_buf_used -= room; }