diff options
Diffstat (limited to 'hw/usb-serial.c')
-rw-r--r-- | hw/usb-serial.c | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/hw/usb-serial.c b/hw/usb-serial.c index 2775cf0f0..c3f340137 100644 --- a/hw/usb-serial.c +++ b/hw/usb-serial.c @@ -497,12 +497,28 @@ static int usb_serial_can_read(void *opaque) static void usb_serial_read(void *opaque, const uint8_t *buf, int size) { USBSerialState *s = opaque; - int first_size = RECV_BUF - s->recv_ptr; - if (first_size > size) - first_size = size; - memcpy(s->recv_buf + s->recv_ptr + s->recv_used, buf, first_size); - if (size > first_size) - memcpy(s->recv_buf, buf + first_size, size - first_size); + int first_size, start; + + /* room in the buffer? */ + if (size > (RECV_BUF - s->recv_used)) + size = RECV_BUF - s->recv_used; + + start = s->recv_ptr + s->recv_used; + if (start < RECV_BUF) { + /* copy data to end of buffer */ + first_size = RECV_BUF - start; + if (first_size > size) + first_size = size; + + memcpy(s->recv_buf + start, buf, first_size); + + /* wrap around to front if needed */ + if (size > first_size) + memcpy(s->recv_buf, buf + first_size, size - first_size); + } else { + start -= RECV_BUF; + memcpy(s->recv_buf + start, buf, size); + } s->recv_used += size; } @@ -583,7 +599,7 @@ static USBDevice *usb_serial_init(const char *filename) qdev_prop_set_uint16(&dev->qdev, "vendorid", vendorid); if (productid) qdev_prop_set_uint16(&dev->qdev, "productid", productid); - qdev_init(&dev->qdev); + qdev_init_nofail(&dev->qdev); return dev; } @@ -599,7 +615,7 @@ static USBDevice *usb_braille_init(const char *unused) dev = usb_create(NULL /* FIXME */, "usb-braille"); qdev_prop_set_chr(&dev->qdev, "chardev", cdrv); - qdev_init(&dev->qdev); + qdev_init_nofail(&dev->qdev); return dev; } |