static int csrhci_write(struct CharDriverState *chr,
                const uint8_t *buf, int len)
{
    struct csrhci_s *s = (struct csrhci_s *) chr->opaque;
    int plen = s->in_len;

    if (!s->enable)
        return 0;

    s->in_len += len;
    memcpy(s->inpkt + plen, buf, len);

    while (1) {
        if (s->in_len >= 2 && plen < 2)
            s->in_hdr = csrhci_header_len(s->inpkt) + 1;

        if (s->in_len >= s->in_hdr && plen < s->in_hdr)
            s->in_data = csrhci_data_len(s->inpkt) + s->in_hdr;

        if (s->in_len >= s->in_data) {
            csrhci_in_packet(s, s->inpkt);

            memmove(s->inpkt, s->inpkt + s->in_len, s->in_len - s->in_data);
            s->in_len -= s->in_data;
            s->in_hdr = INT_MAX;
            s->in_data = INT_MAX;
            plen = 0;
        } else
            break;
    }

    return len;
}
Ejemplo n.º 2
0
static int csrhci_write(struct CharDriverState *chr,
                const uint8_t *buf, int len)
{
    struct csrhci_s *s = (struct csrhci_s *) chr->opaque;
    int total = 0;

    if (!s->enable)
        return 0;

    for (;;) {
        int cnt = MIN(len, s->in_needed - s->in_len);
        if (cnt) {
            memcpy(s->inpkt + s->in_len, buf, cnt);
            s->in_len += cnt;
            buf += cnt;
            len -= cnt;
            total += cnt;
        }

        if (s->in_len < s->in_needed) {
            break;
        }

        if (s->in_state == CSR_HDR_LEN) {
            s->in_hdr = csrhci_header_len(s->inpkt) + 1;
            assert(s->in_hdr >= s->in_needed);
            s->in_needed = s->in_hdr;
            s->in_state = CSR_DATA_LEN;
            continue;
        }

        if (s->in_state == CSR_DATA_LEN) {
            s->in_needed += csrhci_data_len(s->inpkt);
            /* hci_acl_hdr could specify more than 4096 bytes, so assert.  */
            assert(s->in_needed <= sizeof(s->inpkt));
            s->in_state = CSR_DATA;
            continue;
        }

        if (s->in_state == CSR_DATA) {
            csrhci_in_packet(s, s->inpkt);
            csrhci_ready_for_next_inpkt(s);
        }
    }

    return total;
}