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; }
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; }