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 );
    }
}
Пример #3
0
/* 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);
    }
}
Пример #4
0
/* 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;
}