diff --git a/.gitignore b/.gitignore
index 9b14986..fa85789 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,5 @@ qemu-kvm-0.13.0-25fdf4a.tar.gz
 /qemu-kvm-0.14.0-3593e6b.tar.gz
 /qemu-kvm-0.14.0-7aa8c46.tar.gz
 /qemu-kvm-0.15.0-525e3df.tar.gz
+/qemu-kvm-0.15.0-fda1906.tar.gz
+/qemu-kvm-0.15.0-59fadcc.tar.gz
diff --git a/0001-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch b/0001-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch
new file mode 100644
index 0000000..e92a81a
--- /dev/null
+++ b/0001-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch
@@ -0,0 +1,57 @@
+From 47d0d4d2d16bdbb3e80b6c9a29b9db3f81f1d6fd Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 21:57:47 +0100
+Subject: [PATCH 01/13] char: Split out tcp socket close code in a separate
+ function
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+---
+ qemu-char.c |   25 ++++++++++++++++---------
+ 1 files changed, 16 insertions(+), 9 deletions(-)
+
+diff --git a/qemu-char.c b/qemu-char.c
+index dcf7065..1701bdf 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -1945,6 +1945,21 @@ typedef struct {
+ 
+ static void tcp_chr_accept(void *opaque);
+ 
++static void tcp_closed(void *opaque)
++{
++    CharDriverState *chr = opaque;
++    TCPCharDriver *s = chr->opaque;
++
++    s->connected = 0;
++    if (s->listen_fd >= 0) {
++        qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
++    }
++    qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
++    closesocket(s->fd);
++    s->fd = -1;
++    qemu_chr_event(chr, CHR_EVENT_CLOSED);
++}
++
+ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ {
+     TCPCharDriver *s = chr->opaque;
+@@ -2095,15 +2110,7 @@ static void tcp_chr_read(void *opaque)
+         len = s->max_size;
+     size = tcp_chr_recv(chr, (void *)buf, len);
+     if (size == 0) {
+-        /* connection closed */
+-        s->connected = 0;
+-        if (s->listen_fd >= 0) {
+-            qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
+-        }
+-        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+-        closesocket(s->fd);
+-        s->fd = -1;
+-        qemu_chr_event(chr, CHR_EVENT_CLOSED);
++        tcp_closed(chr);
+     } else if (size > 0) {
+         if (s->do_telnetopt)
+             tcp_chr_process_IAC_bytes(chr, s, buf, &size);
+-- 
+1.7.5.1
+
diff --git a/0001-hw-usb-musb.c-Don-t-misuse-usb_packet_complete.patch b/0001-hw-usb-musb.c-Don-t-misuse-usb_packet_complete.patch
deleted file mode 100644
index 135f851..0000000
--- a/0001-hw-usb-musb.c-Don-t-misuse-usb_packet_complete.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From 5b1a8791870cbb83cce780be54da6029be4126a4 Mon Sep 17 00:00:00 2001
-From: Peter Maydell <peter.maydell@linaro.org>
-Date: Tue, 14 Jun 2011 12:24:04 +0100
-Subject: [PATCH 01/35] hw/usb-musb.c: Don't misuse usb_packet_complete()
-
-In musb_packet() handle final processing of non-asynchronous
-USB packets by directly calling musb_schedule_cb() rather than
-going through usb_packet_complete(). The latter will trigger
-an assertion because the packet doesn't belong to a device.
-
-Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb-musb.c |    2 +-
- 1 files changed, 1 insertions(+), 1 deletions(-)
-
-diff --git a/hw/usb-musb.c b/hw/usb-musb.c
-index 21f35afa..d15971f 100644
---- a/hw/usb-musb.c
-+++ b/hw/usb-musb.c
-@@ -616,7 +616,7 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
-     }
- 
-     ep->status[dir] = ret;
--    usb_packet_complete(s->port.dev, &ep->packey[dir].p);
-+    musb_schedule_cb(s->port.dev, &ep->packey[dir].p);
- }
- 
- static void musb_tx_packet_complete(USBPacket *packey, void *opaque)
--- 
-1.7.5.1
-
diff --git a/0002-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch b/0002-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch
new file mode 100644
index 0000000..1fd460c
--- /dev/null
+++ b/0002-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch
@@ -0,0 +1,882 @@
+From ffef9f85d32395989a3c5845dfe34d2110ccb82b Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 20:31:45 +0100
+Subject: [PATCH 02/13] char: Add a QemuChrHandlers struct to initialise
+ chardev handlers
+
+Instead of passing each handler in the qemu_add_handlers() function,
+create a struct of handlers that can be passed to the function instead.
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+---
+ gdbstub.c               |    9 +++++++--
+ hw/ccid-card-passthru.c |   11 +++++++----
+ hw/debugcon.c           |    2 +-
+ hw/escc.c               |    9 +++++++--
+ hw/etraxfs_ser.c        |   13 +++++++++----
+ hw/grlib_apbuart.c      |   12 +++++++-----
+ hw/ivshmem.c            |   28 ++++++++++++++++++++++------
+ hw/lm32_juart.c         |    8 +++++++-
+ hw/lm32_uart.c          |    8 +++++++-
+ hw/mcf_uart.c           |    9 +++++++--
+ hw/milkymist-uart.c     |    8 +++++++-
+ hw/pl011.c              |    9 +++++++--
+ hw/pxa2xx.c             |   13 +++++++++----
+ hw/serial.c             |    9 +++++++--
+ hw/sh_serial.c          |   12 +++++++++---
+ hw/spapr_vty.c          |    8 ++++++--
+ hw/strongarm.c          |   12 +++++++-----
+ hw/syborg_serial.c      |    9 +++++++--
+ hw/usb-serial.c         |    9 +++++++--
+ hw/virtio-console.c     |   11 ++++++++---
+ hw/xen_console.c        |   16 +++++++++++-----
+ hw/xilinx_uartlite.c    |   11 +++++++++--
+ monitor.c               |   18 ++++++++++++++----
+ net/slirp.c             |    8 ++++++--
+ qemu-char.c             |   32 ++++++++++++++++++++++----------
+ qemu-char.h             |   13 +++++++++----
+ usb-redir.c             |    9 +++++++--
+ 27 files changed, 233 insertions(+), 83 deletions(-)
+
+diff --git a/gdbstub.c b/gdbstub.c
+index c085a5a..0ff61cb 100644
+--- a/gdbstub.c
++++ b/gdbstub.c
+@@ -2739,6 +2739,12 @@ static void gdb_sigterm_handler(int signal)
+ }
+ #endif
+ 
++static const QemuChrHandlers gdb_handlers = {
++    .fd_can_read = gdb_chr_can_receive,
++    .fd_read = gdb_chr_receive,
++    .fd_event = gdb_chr_event,
++};
++
+ int gdbserver_start(const char *device)
+ {
+     GDBState *s;
+@@ -2768,8 +2774,7 @@ int gdbserver_start(const char *device)
+         if (!chr)
+             return -1;
+ 
+-        qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
+-                              gdb_chr_event, NULL);
++        qemu_chr_add_handlers(chr, &gdb_handlers, NULL);
+     }
+ 
+     s = gdbserver_state;
+diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
+index 28eb9d1..1dee6f7 100644
+--- a/hw/ccid-card-passthru.c
++++ b/hw/ccid-card-passthru.c
+@@ -273,6 +273,12 @@ static const uint8_t *passthru_get_atr(CCIDCardState *base, uint32_t *len)
+     return card->atr;
+ }
+ 
++static const QemuChrHandlers passthru_handlers = {
++    .fd_can_read = ccid_card_vscard_can_read,
++    .fd_read = ccid_card_vscard_read,
++    .fd_event = ccid_card_vscard_event,
++};
++
+ static int passthru_initfn(CCIDCardState *base)
+ {
+     PassthruState *card = DO_UPCAST(PassthruState, base, base);
+@@ -281,10 +287,7 @@ static int passthru_initfn(CCIDCardState *base)
+     card->vscard_in_hdr = 0;
+     if (card->cs) {
+         DPRINTF(card, D_INFO, "initing chardev\n");
+-        qemu_chr_add_handlers(card->cs,
+-            ccid_card_vscard_can_read,
+-            ccid_card_vscard_read,
+-            ccid_card_vscard_event, card);
++        qemu_chr_add_handlers(card->cs, &passthru_handlers, card);
+         ccid_card_vscard_send_init(card);
+     } else {
+         error_report("missing chardev");
+diff --git a/hw/debugcon.c b/hw/debugcon.c
+index 5ee6821..e79a595 100644
+--- a/hw/debugcon.c
++++ b/hw/debugcon.c
+@@ -73,7 +73,7 @@ static void debugcon_init_core(DebugconState *s)
+         exit(1);
+     }
+ 
+-    qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s);
++    qemu_chr_add_handlers(s->chr, NULL, s);
+ }
+ 
+ static int debugcon_isa_initfn(ISADevice *dev)
+diff --git a/hw/escc.c b/hw/escc.c
+index f6fd919..dfa329a 100644
+--- a/hw/escc.c
++++ b/hw/escc.c
+@@ -898,6 +898,12 @@ void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
+     sysbus_mmio_map(s, 0, base);
+ }
+ 
++static const QemuChrHandlers serial_handlers = {
++    .fd_can_read = serial_can_receive,
++    .fd_read = serial_receive1,
++    .fd_event = serial_event,
++};
++
+ static int escc_init1(SysBusDevice *dev)
+ {
+     SerialState *s = FROM_SYSBUS(SerialState, dev);
+@@ -911,8 +917,7 @@ static int escc_init1(SysBusDevice *dev)
+         s->chn[i].chn = 1 - i;
+         s->chn[i].clock = s->frequency / 2;
+         if (s->chn[i].chr) {
+-            qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
+-                                  serial_receive1, serial_event, &s->chn[i]);
++            qemu_chr_add_handlers(s->chn[i].chr, &serial_handlers, &s->chn[i]);
+         }
+     }
+     s->chn[0].otherchn = &s->chn[1];
+diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
+index b917d4d..ebbad77 100644
+--- a/hw/etraxfs_ser.c
++++ b/hw/etraxfs_ser.c
+@@ -202,6 +202,12 @@ static void etraxfs_ser_reset(DeviceState *d)
+ 
+ }
+ 
++static const QemuChrHandlers serial_handlers = {
++    .fd_can_read = serial_can_receive,
++    .fd_read = serial_receive,
++    .fd_event = serial_event,
++};
++
+ static int etraxfs_ser_init(SysBusDevice *dev)
+ {
+     struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
+@@ -212,10 +218,9 @@ static int etraxfs_ser_init(SysBusDevice *dev)
+                                       DEVICE_NATIVE_ENDIAN);
+     sysbus_init_mmio(dev, R_MAX * 4, ser_regs);
+     s->chr = qdev_init_chardev(&dev->qdev);
+-    if (s->chr)
+-        qemu_chr_add_handlers(s->chr,
+-                      serial_can_receive, serial_receive,
+-                      serial_event, s);
++    if (s->chr) {
++        qemu_chr_add_handlers(s->chr, &serial_handlers, s);
++    }
+     return 0;
+ }
+ 
+diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c
+index 169a56e..310687b 100644
+--- a/hw/grlib_apbuart.c
++++ b/hw/grlib_apbuart.c
+@@ -144,16 +144,18 @@ static CPUWriteMemoryFunc * const grlib_apbuart_write[] = {
+     NULL, NULL, grlib_apbuart_writel,
+ };
+ 
++static const QemuChrHandlers grlib_handlers = {
++    .fd_can_read = grlib_apbuart_can_receive,
++    .fd_read = grlib_apbuart_receive,
++    .fd_event = grlib_apbuart_event,
++};
++
+ static int grlib_apbuart_init(SysBusDevice *dev)
+ {
+     UART *uart      = FROM_SYSBUS(typeof(*uart), dev);
+     int   uart_regs = 0;
+ 
+-    qemu_chr_add_handlers(uart->chr,
+-                          grlib_apbuart_can_receive,
+-                          grlib_apbuart_receive,
+-                          grlib_apbuart_event,
+-                          uart);
++    qemu_chr_add_handlers(uart->chr, &grlib_handlers, uart);
+ 
+     sysbus_init_irq(dev, &uart->irq);
+ 
+diff --git a/hw/ivshmem.c b/hw/ivshmem.c
+index 3055dd2..4f59575 100644
+--- a/hw/ivshmem.c
++++ b/hw/ivshmem.c
+@@ -312,6 +312,18 @@ static void fake_irqfd(void *opaque, const uint8_t *buf, int size) {
+     msix_notify(pdev, entry->vector);
+ }
+ 
++static const QemuChrHandlers ivshmem_handlers = {
++    .fd_can_read = ivshmem_can_receive,
++    .fd_read = ivshmem_receive,
++    .fd_event = ivshmem_event,
++};
++
++static const QemuChrHandlers ivshmem_msi_handlers = {
++    .fd_can_read = ivshmem_can_receive,
++    .fd_read = fake_irqfd,
++    .fd_event = ivshmem_event,
++};
++
+ static CharDriverState* create_eventfd_chr_device(void * opaque, int eventfd,
+                                                                     int vector)
+ {
+@@ -331,11 +343,10 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, int eventfd,
+         s->eventfd_table[vector].pdev = &s->dev;
+         s->eventfd_table[vector].vector = vector;
+ 
+-        qemu_chr_add_handlers(chr, ivshmem_can_receive, fake_irqfd,
+-                      ivshmem_event, &s->eventfd_table[vector]);
++        qemu_chr_add_handlers(chr, &ivshmem_msi_handlers,
++                              &s->eventfd_table[vector]);
+     } else {
+-        qemu_chr_add_handlers(chr, ivshmem_can_receive, ivshmem_receive,
+-                      ivshmem_event, s);
++        qemu_chr_add_handlers(chr, &ivshmem_handlers, s);
+     }
+ 
+     return chr;
+@@ -666,6 +677,12 @@ static int ivshmem_load(QEMUFile* f, void *opaque, int version_id)
+     return 0;
+ }
+ 
++static const QemuChrHandlers ivshmem_server_handlers = {
++    .fd_can_read = ivshmem_can_receive,
++    .fd_read = ivshmem_read,
++    .fd_event = ivshmem_event,
++};
++
+ static int pci_ivshmem_init(PCIDevice *dev)
+ {
+     IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev);
+@@ -749,8 +766,7 @@ static int pci_ivshmem_init(PCIDevice *dev)
+ 
+         s->eventfd_chr = qemu_mallocz(s->vectors * sizeof(CharDriverState *));
+ 
+-        qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive, ivshmem_read,
+-                     ivshmem_event, s);
++        qemu_chr_add_handlers(s->server_chr, &ivshmem_server_handlers, s);
+     } else {
+         /* just map the file immediately, we're not using a server */
+         int fd;
+diff --git a/hw/lm32_juart.c b/hw/lm32_juart.c
+index fddcf7e..12dd1e8 100644
+--- a/hw/lm32_juart.c
++++ b/hw/lm32_juart.c
+@@ -110,13 +110,19 @@ static void juart_reset(DeviceState *d)
+     s->jrx = 0;
+ }
+ 
++static const QemuChrHandlers juart_handlers = {
++    .fd_can_read = juart_can_rx,
++    .fd_read = juart_rx,
++    .fd_event = juart_event,
++};
++
+ static int lm32_juart_init(SysBusDevice *dev)
+ {
+     LM32JuartState *s = FROM_SYSBUS(typeof(*s), dev);
+ 
+     s->chr = qdev_init_chardev(&dev->qdev);
+     if (s->chr) {
+-        qemu_chr_add_handlers(s->chr, juart_can_rx, juart_rx, juart_event, s);
++        qemu_chr_add_handlers(s->chr, juart_handlers, s);
+     }
+ 
+     return 0;
+diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c
+index 09090e9..5438660 100644
+--- a/hw/lm32_uart.c
++++ b/hw/lm32_uart.c
+@@ -242,6 +242,12 @@ static void uart_reset(DeviceState *d)
+     s->regs[R_LSR] = LSR_THRE | LSR_TEMT;
+ }
+ 
++static const QemuChrHandlers uart_handlers = {
++    .fd_can_read = uart_can_rx,
++    .fd_read = uart_rx,
++    .fd_event = uart_event,
++};
++
+ static int lm32_uart_init(SysBusDevice *dev)
+ {
+     LM32UartState *s = FROM_SYSBUS(typeof(*s), dev);
+@@ -255,7 +261,7 @@ static int lm32_uart_init(SysBusDevice *dev)
+ 
+     s->chr = qdev_init_chardev(&dev->qdev);
+     if (s->chr) {
+-        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
++        qemu_chr_add_handlers(s->chr, uart_handlers, s);
+     }
+ 
+     return 0;
+diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c
+index 905e116..bb5740c 100644
+--- a/hw/mcf_uart.c
++++ b/hw/mcf_uart.c
+@@ -268,6 +268,12 @@ static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size)
+     mcf_uart_push_byte(s, buf[0]);
+ }
+ 
++static const QemuChrHandlers mcf_uart_handlers = {
++    .fd_can_read = mcf_uart_can_receive,
++    .fd_read = mcf_uart_receive,
++    .fd_event = mcf_uart_event,
++};
++
+ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
+ {
+     mcf_uart_state *s;
+@@ -276,8 +282,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
+     s->chr = chr;
+     s->irq = irq;
+     if (chr) {
+-        qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
+-                              mcf_uart_event, s);
++        qemu_chr_add_handlers(chr, &mcf_uart_handlers, s);
+     }
+     mcf_uart_reset(s);
+     return s;
+diff --git a/hw/milkymist-uart.c b/hw/milkymist-uart.c
+index 56c90da..4412b1b 100644
+--- a/hw/milkymist-uart.c
++++ b/hw/milkymist-uart.c
+@@ -133,6 +133,12 @@ static void milkymist_uart_reset(DeviceState *d)
+     }
+ }
+ 
++static const QemuChrHandlers uart_handlers = {
++    .fd_can_read = uart_can_rx,
++    .fd_read = uart_rx,
++    .fd_event = uart_event,
++};
++
+ static int milkymist_uart_init(SysBusDevice *dev)
+ {
+     MilkymistUartState *s = FROM_SYSBUS(typeof(*s), dev);
+@@ -147,7 +153,7 @@ static int milkymist_uart_init(SysBusDevice *dev)
+ 
+     s->chr = qdev_init_chardev(&dev->qdev);
+     if (s->chr) {
+-        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
++        qemu_chr_add_handlers(s->chr, uart_handlers, s);
+     }
+ 
+     return 0;
+diff --git a/hw/pl011.c b/hw/pl011.c
+index 997ce84..37ba7f6 100644
+--- a/hw/pl011.c
++++ b/hw/pl011.c
+@@ -260,6 +260,12 @@ static const VMStateDescription vmstate_pl011 = {
+     }
+ };
+ 
++static const QemuChrHandlers pl011_handlers = {
++    .fd_can_read = pl011_can_receive,
++    .fd_read = pl011_receive,
++    .fd_event = pl011_event,
++};
++
+ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
+ {
+     int iomemtype;
+@@ -278,8 +284,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
+     s->cr = 0x300;
+     s->flags = 0x90;
+     if (s->chr) {
+-        qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
+-                              pl011_event, s);
++        qemu_chr_add_handlers(s->chr, &pl011_handlers, s);
+     }
+     vmstate_register(&dev->qdev, -1, &vmstate_pl011, s);
+     return 0;
+diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
+index cf93110..18bbe48 100644
+--- a/hw/pxa2xx.c
++++ b/hw/pxa2xx.c
+@@ -2019,6 +2019,12 @@ static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id)
+     return 0;
+ }
+ 
++static const QemuChrHandlers pxa2xx_handlers = {
++    .fd_can_read = pxa2xx_fir_is_empty,
++    .fd_read = pxa2xx_fir_rx,
++    .fd_event = pxa2xx_fir_event,
++};
++
+ static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
+                 qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma,
+                 CharDriverState *chr)
+@@ -2038,10 +2044,9 @@ static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
+                     pxa2xx_fir_writefn, s, DEVICE_NATIVE_ENDIAN);
+     cpu_register_physical_memory(base, 0x1000, iomemtype);
+ 
+-    if (chr)
+-        qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
+-                        pxa2xx_fir_rx, pxa2xx_fir_event, s);
+-
++    if (chr) {
++        qemu_chr_add_handlers(chr, &pxa2xx_handlers, s);
++    }
+     register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
+                     pxa2xx_fir_load, s);
+ 
+diff --git a/hw/serial.c b/hw/serial.c
+index 0ee61dd..d496bcf 100644
+--- a/hw/serial.c
++++ b/hw/serial.c
+@@ -727,6 +727,12 @@ static void serial_reset(void *opaque)
+     qemu_irq_lower(s->irq);
+ }
+ 
++static const QemuChrHandlers serial_handlers = {
++    .fd_can_read = serial_can_receive1,
++    .fd_read = serial_receive1,
++    .fd_event = serial_event,
++};
++
+ static void serial_init_core(SerialState *s)
+ {
+     if (!s->chr) {
+@@ -741,8 +747,7 @@ static void serial_init_core(SerialState *s)
+ 
+     qemu_register_reset(serial_reset, s);
+ 
+-    qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
+-                          serial_event, s);
++    qemu_chr_add_handlers(s->chr, &serial_handlers, s);
+ }
+ 
+ /* Change the main reference oscillator frequency. */
+diff --git a/hw/sh_serial.c b/hw/sh_serial.c
+index 191f4a6..8b6460d 100644
+--- a/hw/sh_serial.c
++++ b/hw/sh_serial.c
+@@ -350,6 +350,12 @@ static CPUWriteMemoryFunc * const sh_serial_writefn[] = {
+     &sh_serial_write,
+ };
+ 
++static const QemuChrHandlers sh_serial_handlers = {
++    .fd_can_read = sh_serial_can_receive1,
++    .fd_read = sh_serial_receive1,
++    .fd_event = sh_serial_event,
++};
++
+ void sh_serial_init (target_phys_addr_t base, int feat,
+ 		     uint32_t freq, CharDriverState *chr,
+ 		     qemu_irq eri_source,
+@@ -389,9 +395,9 @@ void sh_serial_init (target_phys_addr_t base, int feat,
+ 
+     s->chr = chr;
+ 
+-    if (chr)
+-        qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
+-			      sh_serial_event, s);
++    if (chr) {
++        qemu_chr_add_handlers(chr, &sh_serial_handlers, s);
++    }
+ 
+     s->eri = eri_source;
+     s->rxi = rxi_source;
+diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
+index 6fc0105..5968d85 100644
+--- a/hw/spapr_vty.c
++++ b/hw/spapr_vty.c
+@@ -54,12 +54,16 @@ void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
+     qemu_chr_write(dev->chardev, buf, len);
+ }
+ 
++static const QemuChrHandlers vty_handlers = {
++    .fd_can_read = vty_can_receive,
++    .fd_read = vty_receive,
++};
++
+ static int spapr_vty_init(VIOsPAPRDevice *sdev)
+ {
+     VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
+ 
+-    qemu_chr_add_handlers(dev->chardev, vty_can_receive,
+-                          vty_receive, NULL, dev);
++    qemu_chr_add_handlers(dev->chardev, vty_handlers, dev);
+ 
+     return 0;
+ }
+diff --git a/hw/strongarm.c b/hw/strongarm.c
+index 0e03d61..c2dce95 100644
+--- a/hw/strongarm.c
++++ b/hw/strongarm.c
+@@ -1188,6 +1188,12 @@ static CPUWriteMemoryFunc * const strongarm_uart_writefn[] = {
+     strongarm_uart_write,
+ };
+ 
++static const QemuChrHandlers strongarm_uart_handlers = {
++    .fd_can_read = strongarm_uart_can_receive,
++    .fd_read = strongarm_uart_receive,
++    .fd_event = strongarm_uart_event,
++};
++
+ static int strongarm_uart_init(SysBusDevice *dev)
+ {
+     StrongARMUARTState *s = FROM_SYSBUS(StrongARMUARTState, dev);
+@@ -1202,11 +1208,7 @@ static int strongarm_uart_init(SysBusDevice *dev)
+     s->tx_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_tx, s);
+ 
+     if (s->chr) {
+-        qemu_chr_add_handlers(s->chr,
+-                        strongarm_uart_can_receive,
+-                        strongarm_uart_receive,
+-                        strongarm_uart_event,
+-                        s);
++        qemu_chr_add_handlers(s->chr, &strongarm_uart_handlers, s);
+     }
+ 
+     return 0;
+diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
+index 2ef7175..ac68022 100644
+--- a/hw/syborg_serial.c
++++ b/hw/syborg_serial.c
+@@ -292,6 +292,12 @@ static const VMStateDescription vmstate_syborg_serial = {
+     }
+ };
+ 
++static const QemuChrHandlers syborg_serial_handlers = {
++    .fd_can_read = syborg_serial_can_receive,
++    .fd_read = syborg_serial_receive,
++    .fd_event = syborg_serial_event,
++};
++
+ static int syborg_serial_init(SysBusDevice *dev)
+ {
+     SyborgSerialState *s = FROM_SYSBUS(SyborgSerialState, dev);
+@@ -304,8 +310,7 @@ static int syborg_serial_init(SysBusDevice *dev)
+     sysbus_init_mmio(dev, 0x1000, iomemtype);
+     s->chr = qdev_init_chardev(&dev->qdev);
+     if (s->chr) {
+-        qemu_chr_add_handlers(s->chr, syborg_serial_can_receive,
+-                              syborg_serial_receive, syborg_serial_event, s);
++        qemu_chr_add_handlers(s->chr, &syborg_serial_handlers, s);
+     }
+     if (s->fifo_size <= 0) {
+         fprintf(stderr, "syborg_serial: fifo too small\n");
+diff --git a/hw/usb-serial.c b/hw/usb-serial.c
+index c69c437..45d48ee 100644
+--- a/hw/usb-serial.c
++++ b/hw/usb-serial.c
+@@ -476,6 +476,12 @@ static void usb_serial_event(void *opaque, int event)
+     }
+ }
+ 
++static const QemuChrHandlers usb_serial_handlers = {
++    .fd_can_read = usb_serial_can_read,
++    .fd_read = usb_serial_read,
++    .fd_event = usb_serial_event,
++};
++
+ static int usb_serial_initfn(USBDevice *dev)
+ {
+     USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
+@@ -487,8 +493,7 @@ static int usb_serial_initfn(USBDevice *dev)
+         return -1;
+     }
+ 
+-    qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
+-                          usb_serial_event, s);
++    qemu_chr_add_handlers(s->cs, &usb_serial_handlers, s);
+     usb_serial_handle_reset(dev);
+     return 0;
+ }
+diff --git a/hw/virtio-console.c b/hw/virtio-console.c
+index fe5e188..cfc3087 100644
+--- a/hw/virtio-console.c
++++ b/hw/virtio-console.c
+@@ -95,6 +95,12 @@ static void chr_event(void *opaque, int event)
+     }
+ }
+ 
++static const QemuChrHandlers chr_handlers = {
++    .fd_can_read = chr_can_read,
++    .fd_read = chr_read,
++    .fd_event = chr_event,
++};
++
+ static int virtconsole_initfn(VirtIOSerialPort *port)
+ {
+     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
+@@ -107,8 +113,7 @@ static int virtconsole_initfn(VirtIOSerialPort *port)
+     }
+ 
+     if (vcon->chr) {
+-        qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
+-                              vcon);
++        qemu_chr_add_handlers(vcon->chr, &chr_handlers, vcon);
+         info->have_data = flush_buf;
+         info->guest_open = guest_open;
+         info->guest_close = guest_close;
+@@ -126,7 +131,7 @@ static int virtconsole_exitfn(VirtIOSerialPort *port)
+ 	 * Instead of closing the chardev, free it so it can be used
+ 	 * for other purposes.
+ 	 */
+-	qemu_chr_add_handlers(vcon->chr, NULL, NULL, NULL, NULL);
++	qemu_chr_add_handlers(vcon->chr, NULL, NULL);
+     }
+ 
+     return 0;
+diff --git a/hw/xen_console.c b/hw/xen_console.c
+index 8ef104c..85e8a22 100644
+--- a/hw/xen_console.c
++++ b/hw/xen_console.c
+@@ -212,6 +212,11 @@ out:
+     return ret;
+ }
+ 
++static const QemuChrHandlers xencons_handlers = {
++    .fd_can_read = xencons_can_receive,
++    .fd_read = xencons_receive,
++};
++
+ static int con_connect(struct XenDevice *xendev)
+ {
+     struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
+@@ -232,9 +237,9 @@ static int con_connect(struct XenDevice *xendev)
+ 	return -1;
+ 
+     xen_be_bind_evtchn(&con->xendev);
+-    if (con->chr)
+-        qemu_chr_add_handlers(con->chr, xencons_can_receive, xencons_receive,
+-                              NULL, con);
++    if (con->chr) {
++        qemu_chr_add_handlers(con->chr, &xencons_handlers, con);
++    }
+ 
+     xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
+ 		  con->ring_ref,
+@@ -248,8 +253,9 @@ static void con_disconnect(struct XenDevice *xendev)
+ {
+     struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
+ 
+-    if (con->chr)
+-        qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
++    if (con->chr) {
++        qemu_chr_add_handlers(con->chr, NULL, NULL);
++    }
+     xen_be_unbind_evtchn(&con->xendev);
+ 
+     if (con->sring) {
+diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
+index 9b94e98..1845577 100644
+--- a/hw/xilinx_uartlite.c
++++ b/hw/xilinx_uartlite.c
+@@ -193,6 +193,12 @@ static void uart_event(void *opaque, int event)
+ 
+ }
+ 
++static const QemuChrHandlers uart_handlers = {
++    .fd_can_read = uart_can_rx,
++    .fd_read = uart_rx,
++    .fd_event = uart_event,
++};
++
+ static int xilinx_uartlite_init(SysBusDevice *dev)
+ {
+     struct xlx_uartlite *s = FROM_SYSBUS(typeof (*s), dev);
+@@ -206,8 +212,9 @@ static int xilinx_uartlite_init(SysBusDevice *dev)
+     sysbus_init_mmio(dev, R_MAX * 4, uart_regs);
+ 
+     s->chr = qdev_init_chardev(&dev->qdev);
+-    if (s->chr)
+-        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
++    if (s->chr) {
++        qemu_chr_add_handlers(s->chr, &uart_handlers, s);
++    }
+     return 0;
+ }
+ 
+diff --git a/monitor.c b/monitor.c
+index 718935b..5b79dde 100644
+--- a/monitor.c
++++ b/monitor.c
+@@ -5249,6 +5249,18 @@ static void monitor_event(void *opaque, int event)
+  * End:
+  */
+ 
++static const QemuChrHandlers monitor_handlers = {
++    .fd_can_read = monitor_can_read,
++    .fd_read = monitor_read,
++    .fd_event = monitor_event,
++};
++
++static const QemuChrHandlers monitor_control_handlers = {
++    .fd_can_read = monitor_can_read,
++    .fd_read = monitor_control_read,
++    .fd_event = monitor_control_event,
++};
++
+ void monitor_init(CharDriverState *chr, int flags)
+ {
+     static int is_first_init = 1;
+@@ -5271,12 +5283,10 @@ void monitor_init(CharDriverState *chr, int flags)
+     if (monitor_ctrl_mode(mon)) {
+         mon->mc = qemu_mallocz(sizeof(MonitorControl));
+         /* Control mode requires special handlers */
+-        qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read,
+-                              monitor_control_event, mon);
++        qemu_chr_add_handlers(chr, &monitor_control_handlers, mon);
+         qemu_chr_set_echo(chr, true);
+     } else {
+-        qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
+-                              monitor_event, mon);
++        qemu_chr_add_handlers(chr, &monitor_handlers, mon);
+     }
+ 
+     QLIST_INSERT_HEAD(&mon_list, mon, entry);
+diff --git a/net/slirp.c b/net/slirp.c
+index 157b80a..8eeec7e 100644
+--- a/net/slirp.c
++++ b/net/slirp.c
+@@ -577,6 +577,11 @@ static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
+     slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size);
+ }
+ 
++static const QemuChrHandlers guestfwd_handlers = {
++    .fd_can_read = guestfwd_can_read,
++    .fd_read = guestfwd_read,
++};
++
+ static int slirp_guestfwd(SlirpState *s, const char *config_str,
+                           int legacy_format)
+ {
+@@ -633,8 +638,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
+     fwd->port = port;
+     fwd->slirp = s->slirp;
+ 
+-    qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
+-                          NULL, fwd);
++    qemu_chr_add_handlers(fwd->hd, &guestfwd_handlers, fwd);
+     return 0;
+ 
+  fail_syntax:
+diff --git a/qemu-char.c b/qemu-char.c
+index 1701bdf..1c33828 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -195,19 +195,26 @@ void qemu_chr_send_event(CharDriverState *s, int event)
+         s->chr_send_event(s, event);
+ }
+ 
++static const QemuChrHandlers null_handlers = {
++    /* All handlers are initialised to NULL */
++};
++
+ void qemu_chr_add_handlers(CharDriverState *s,
+-                           IOCanReadHandler *fd_can_read,
+-                           IOReadHandler *fd_read,
+-                           IOEventHandler *fd_event,
+-                           void *opaque)
++                           const QemuChrHandlers *handlers, void *opaque)
+ {
+-    if (!opaque && !fd_can_read && !fd_read && !fd_event) {
++    if (!s) {
++        return;
++    }
++    if (!opaque && !handlers) {
+         /* chr driver being released. */
+         ++s->avail_connections;
+     }
+-    s->chr_can_read = fd_can_read;
+-    s->chr_read = fd_read;
+-    s->chr_event = fd_event;
++    if (!handlers) {
++        handlers = &null_handlers;
++    }
++    s->chr_can_read = handlers->fd_can_read;
++    s->chr_read = handlers->fd_read;
++    s->chr_event = handlers->fd_event;
+     s->handler_opaque = opaque;
+     if (s->chr_update_read_handler)
+         s->chr_update_read_handler(s);
+@@ -447,6 +454,12 @@ static void mux_chr_event(void *opaque, int event)
+         mux_chr_send_event(d, i, event);
+ }
+ 
++static const QemuChrHandlers mux_chr_handlers = {
++    .fd_can_read = mux_chr_can_read,
++    .fd_read = mux_chr_read,
++    .fd_event = mux_chr_event,
++};
++
+ static void mux_chr_update_read_handler(CharDriverState *chr)
+ {
+     MuxDriver *d = chr->opaque;
+@@ -461,8 +474,7 @@ static void mux_chr_update_read_handler(CharDriverState *chr)
+     d->chr_event[d->mux_cnt] = chr->chr_event;
+     /* Fix up the real driver with mux routines */
+     if (d->mux_cnt == 0) {
+-        qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read,
+-                              mux_chr_event, chr);
++        qemu_chr_add_handlers(d->drv, &mux_chr_handlers, chr);
+     }
+     if (d->focus != -1) {
+         mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
+diff --git a/qemu-char.h b/qemu-char.h
+index f361c6d..b8372ea 100644
+--- a/qemu-char.h
++++ b/qemu-char.h
+@@ -1,6 +1,7 @@
+ #ifndef QEMU_CHAR_H
+ #define QEMU_CHAR_H
+ 
++#include <stdbool.h>
+ #include "qemu-common.h"
+ #include "qemu-queue.h"
+ #include "qemu-option.h"
+@@ -77,6 +78,13 @@ struct CharDriverState {
+     QTAILQ_ENTRY(CharDriverState) next;
+ };
+ 
++typedef struct QemuChrHandlers {
++    IOCanReadHandler *fd_can_read;
++    IOReadHandler *fd_read;
++    IOHandler *fd_write_unblocked;
++    IOEventHandler *fd_event;
++} QemuChrHandlers;
++
+ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
+ CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
+                                     void (*init)(struct CharDriverState *s));
+@@ -89,10 +97,7 @@ void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
+     GCC_FMT_ATTR(2, 3);
+ int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
+ void qemu_chr_send_event(CharDriverState *s, int event);
+-void qemu_chr_add_handlers(CharDriverState *s,
+-                           IOCanReadHandler *fd_can_read,
+-                           IOReadHandler *fd_read,
+-                           IOEventHandler *fd_event,
++void qemu_chr_add_handlers(CharDriverState *s, const QemuChrHandlers *handlers,
+                            void *opaque);
+ int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg);
+ void qemu_chr_generic_open(CharDriverState *s);
+diff --git a/usb-redir.c b/usb-redir.c
+index e212993..e2b5a2c 100644
+--- a/usb-redir.c
++++ b/usb-redir.c
+@@ -782,6 +782,12 @@ static void usbredir_chardev_event(void *opaque, int event)
+     }
+ }
+ 
++static const QemuChrHandlers usbredir_chr_handlers = {
++    .fd_can_read = usbredir_chardev_can_read,
++    .fd_read = usbredir_chardev_read,
++    .fd_event = usbredir_chardev_event,
++};
++
+ /*
+  * init + destroy
+  */
+@@ -807,8 +813,7 @@ static int usbredir_initfn(USBDevice *udev)
+     /* We'll do the attach once we receive the speed from the usb-host */
+     udev->auto_attach = 0;
+ 
+-    qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
+-                          usbredir_chardev_read, usbredir_chardev_event, dev);
++    qemu_chr_add_handlers(dev->cs, &usbredir_chr_handlers, dev);
+ 
+     return 0;
+ }
+-- 
+1.7.5.1
+
diff --git a/0002-usb-Add-a-usb_fill_port-helper-function.patch b/0002-usb-Add-a-usb_fill_port-helper-function.patch
deleted file mode 100644
index 43ea3cf..0000000
--- a/0002-usb-Add-a-usb_fill_port-helper-function.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From dc1a2be79b202d353d320393445ccd9db6263371 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Thu, 30 Jun 2011 11:57:57 +0200
-Subject: [PATCH 02/35] usb: Add a usb_fill_port helper function
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb-bus.c |   10 ++++++++--
- 1 files changed, 8 insertions(+), 2 deletions(-)
-
-diff --git a/hw/usb-bus.c b/hw/usb-bus.c
-index 2abce12..776974e 100644
---- a/hw/usb-bus.c
-+++ b/hw/usb-bus.c
-@@ -140,8 +140,8 @@ USBDevice *usb_create_simple(USBBus *bus, const char *name)
-     return dev;
- }
- 
--void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
--                       USBPortOps *ops, int speedmask)
-+static void usb_fill_port(USBPort *port, void *opaque, int index,
-+                          USBPortOps *ops, int speedmask)
- {
-     port->opaque = opaque;
-     port->index = index;
-@@ -149,6 +149,12 @@ void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
-     port->index = index;
-     port->ops = ops;
-     port->speedmask = speedmask;
-+}
-+
-+void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
-+                       USBPortOps *ops, int speedmask)
-+{
-+    usb_fill_port(port, opaque, index, ops, speedmask);
-     QTAILQ_INSERT_TAIL(&bus->free, port, next);
-     bus->nfree++;
- }
--- 
-1.7.5.1
-
diff --git a/0003-iohandlers-Add-enable-disable_write_fd_handler-funct.patch b/0003-iohandlers-Add-enable-disable_write_fd_handler-funct.patch
new file mode 100644
index 0000000..cb2c9a2
--- /dev/null
+++ b/0003-iohandlers-Add-enable-disable_write_fd_handler-funct.patch
@@ -0,0 +1,77 @@
+From cb93720645e20825259dbb4d2f833b05a98e3062 Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 20:32:58 +0100
+Subject: [PATCH 03/13] iohandlers: Add enable/disable_write_fd_handler()
+ functions
+
+These will be used to provide a cleaner API for the nonblocking case.
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+---
+ iohandler.c |   35 +++++++++++++++++++++++++++++++++++
+ qemu-char.h |    3 +++
+ 2 files changed, 38 insertions(+), 0 deletions(-)
+
+diff --git a/iohandler.c b/iohandler.c
+index 2b82421..8e6628b 100644
+--- a/iohandler.c
++++ b/iohandler.c
+@@ -44,6 +44,41 @@ typedef struct IOHandlerRecord {
+ static QLIST_HEAD(, IOHandlerRecord) io_handlers =
+     QLIST_HEAD_INITIALIZER(io_handlers);
+ 
++static IOHandlerRecord *find_iohandler(int fd)
++{
++    IOHandlerRecord *ioh;
++
++    QLIST_FOREACH(ioh, &io_handlers, next) {
++        if (ioh->fd == fd) {
++            return ioh;
++        }
++    }
++    return NULL;
++}
++
++void enable_write_fd_handler(int fd, IOHandler *fd_write)
++{
++    IOHandlerRecord *ioh;
++
++    ioh = find_iohandler(fd);
++    if (!ioh) {
++        return;
++    }
++
++    ioh->fd_write = fd_write;
++}
++
++void disable_write_fd_handler(int fd)
++{
++    IOHandlerRecord *ioh;
++
++    ioh = find_iohandler(fd);
++    if (!ioh) {
++        return;
++    }
++
++    ioh->fd_write = NULL;
++}
+ 
+ /* XXX: fd_read_poll should be suppressed, but an API change is
+    necessary in the character devices to suppress fd_can_read(). */
+diff --git a/qemu-char.h b/qemu-char.h
+index b8372ea..9fe1b82 100644
+--- a/qemu-char.h
++++ b/qemu-char.h
+@@ -123,6 +123,9 @@ size_t qemu_chr_mem_osize(const CharDriverState *chr);
+ 
+ /* async I/O support */
+ 
++void enable_write_fd_handler(int fd, IOHandler *fd_write);
++void disable_write_fd_handler(int fd);
++
+ int qemu_set_fd_handler2(int fd,
+                          IOCanReadHandler *fd_read_poll,
+                          IOHandler *fd_read,
+-- 
+1.7.5.1
+
diff --git a/0003-usb-Move-initial-call-of-usb_port_location-to-usb_fi.patch b/0003-usb-Move-initial-call-of-usb_port_location-to-usb_fi.patch
deleted file mode 100644
index cba122d..0000000
--- a/0003-usb-Move-initial-call-of-usb_port_location-to-usb_fi.patch
+++ /dev/null
@@ -1,83 +0,0 @@
-From 397fed3bc9bf6dd0e8e18c5be077897299e5c4e2 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Thu, 30 Jun 2011 12:05:19 +0200
-Subject: [PATCH 03/35] usb: Move (initial) call of usb_port_location to
- usb_fill_port
-
-Cleanup / preparation patch for companion controller support. Note that
-as a "side-effect" this patch also fixes the milkymist-softusb controller
-not having a port_location set for its ports.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb-bus.c  |    1 +
- hw/usb-ehci.c |    1 -
- hw/usb-musb.c |    1 -
- hw/usb-ohci.c |    1 -
- hw/usb-uhci.c |    1 -
- 5 files changed, 1 insertions(+), 4 deletions(-)
-
-diff --git a/hw/usb-bus.c b/hw/usb-bus.c
-index 776974e..e37e8a2 100644
---- a/hw/usb-bus.c
-+++ b/hw/usb-bus.c
-@@ -149,6 +149,7 @@ static void usb_fill_port(USBPort *port, void *opaque, int index,
-     port->index = index;
-     port->ops = ops;
-     port->speedmask = speedmask;
-+    usb_port_location(port, NULL, index + 1);
- }
- 
- void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
-diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
-index 91fb7de..88cb2c2 100644
---- a/hw/usb-ehci.c
-+++ b/hw/usb-ehci.c
-@@ -2206,7 +2206,6 @@ static int usb_ehci_initfn(PCIDevice *dev)
-     for(i = 0; i < NB_PORTS; i++) {
-         usb_register_port(&s->bus, &s->ports[i], s, i, &ehci_port_ops,
-                           USB_SPEED_MASK_HIGH);
--        usb_port_location(&s->ports[i], NULL, i+1);
-         s->ports[i].dev = 0;
-     }
- 
-diff --git a/hw/usb-musb.c b/hw/usb-musb.c
-index d15971f..84e6017 100644
---- a/hw/usb-musb.c
-+++ b/hw/usb-musb.c
-@@ -369,7 +369,6 @@ struct MUSBState *musb_init(qemu_irq *irqs)
-     usb_bus_new(&s->bus, &musb_bus_ops, NULL /* FIXME */);
-     usb_register_port(&s->bus, &s->port, s, 0, &musb_port_ops,
-                       USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
--    usb_port_location(&s->port, NULL, 1);
- 
-     return s;
- }
-diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
-index 1c29b9f..95e4623 100644
---- a/hw/usb-ohci.c
-+++ b/hw/usb-ohci.c
-@@ -1742,7 +1742,6 @@ static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
-     for (i = 0; i < num_ports; i++) {
-         usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, &ohci_port_ops,
-                           USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
--        usb_port_location(&ohci->rhport[i].port, NULL, i+1);
-     }
- 
-     ohci->async_td = 0;
-diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
-index 405fa7b..fd25d2a 100644
---- a/hw/usb-uhci.c
-+++ b/hw/usb-uhci.c
-@@ -1129,7 +1129,6 @@ static int usb_uhci_common_initfn(PCIDevice *dev)
-     for(i = 0; i < NB_PORTS; i++) {
-         usb_register_port(&s->bus, &s->ports[i].port, s, i, &uhci_port_ops,
-                           USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
--        usb_port_location(&s->ports[i].port, NULL, i+1);
-     }
-     s->frame_timer = qemu_new_timer_ns(vm_clock, uhci_frame_timer, s);
-     s->num_ports_vmstate = NB_PORTS;
--- 
-1.7.5.1
-
diff --git a/0004-char-Add-framework-for-a-write-unblocked-callback.patch b/0004-char-Add-framework-for-a-write-unblocked-callback.patch
new file mode 100644
index 0000000..36ec50d
--- /dev/null
+++ b/0004-char-Add-framework-for-a-write-unblocked-callback.patch
@@ -0,0 +1,61 @@
+From 66945912c4bd1bc70f3221288a4e7acc5717b336 Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 21:41:42 +0100
+Subject: [PATCH 04/13] char: Add framework for a 'write unblocked' callback
+
+The char layer can let users know that the driver will block on further
+input.  For users interested in not blocking, they can assign a function
+pointer that will be called back when the driver becomes writable.  This
+patch just adds the function pointers to the CharDriverState structure,
+future patches will enable the nonblocking and callback functionality.
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+---
+ qemu-char.c |    3 +++
+ qemu-char.h |    4 ++++
+ 2 files changed, 7 insertions(+), 0 deletions(-)
+
+diff --git a/qemu-char.c b/qemu-char.c
+index 1c33828..ec4eb68 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -214,11 +214,14 @@ void qemu_chr_add_handlers(CharDriverState *s,
+     }
+     s->chr_can_read = handlers->fd_can_read;
+     s->chr_read = handlers->fd_read;
++    s->chr_write_unblocked = handlers->fd_write_unblocked;
+     s->chr_event = handlers->fd_event;
+     s->handler_opaque = opaque;
+     if (s->chr_update_read_handler)
+         s->chr_update_read_handler(s);
+ 
++    s->write_blocked = false;
++
+     /* We're connecting to an already opened device, so let's make sure we
+        also get the open event */
+     if (s->opened) {
+diff --git a/qemu-char.h b/qemu-char.h
+index 9fe1b82..68e7b5b 100644
+--- a/qemu-char.h
++++ b/qemu-char.h
+@@ -62,6 +62,9 @@ struct CharDriverState {
+     IOEventHandler *chr_event;
+     IOCanReadHandler *chr_can_read;
+     IOReadHandler *chr_read;
++    IOHandler *chr_write_unblocked;
++    void (*chr_enable_write_fd_handler)(struct CharDriverState *chr);
++    void (*chr_disable_write_fd_handler)(struct CharDriverState *chr);
+     void *handler_opaque;
+     void (*chr_send_event)(struct CharDriverState *chr, int event);
+     void (*chr_close)(struct CharDriverState *chr);
+@@ -75,6 +78,7 @@ struct CharDriverState {
+     char *filename;
+     int opened;
+     int avail_connections;
++    bool write_blocked; /* Are we in a blocked state? */
+     QTAILQ_ENTRY(CharDriverState) next;
+ };
+ 
+-- 
+1.7.5.1
+
diff --git a/0004-usb-Add-a-register_companion-USB-bus-op.patch b/0004-usb-Add-a-register_companion-USB-bus-op.patch
deleted file mode 100644
index 3cdd193..0000000
--- a/0004-usb-Add-a-register_companion-USB-bus-op.patch
+++ /dev/null
@@ -1,82 +0,0 @@
-From fc63639374684dae600d200c133adad75044e587 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Fri, 24 Jun 2011 11:29:56 +0200
-Subject: [PATCH 04/35] usb: Add a register_companion USB bus op.
-
-This is a preparation patch for adding support for USB companion controllers.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb-bus.c |   31 +++++++++++++++++++++++++++++++
- hw/usb.h     |    5 +++++
- 2 files changed, 36 insertions(+), 0 deletions(-)
-
-diff --git a/hw/usb-bus.c b/hw/usb-bus.c
-index e37e8a2..b511bac 100644
---- a/hw/usb-bus.c
-+++ b/hw/usb-bus.c
-@@ -160,6 +160,37 @@ void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
-     bus->nfree++;
- }
- 
-+int usb_register_companion(const char *masterbus, USBPort *ports[],
-+                           uint32_t portcount, uint32_t firstport,
-+                           void *opaque, USBPortOps *ops, int speedmask)
-+{
-+    USBBus *bus;
-+    int i;
-+
-+    QTAILQ_FOREACH(bus, &busses, next) {
-+        if (strcmp(bus->qbus.name, masterbus) == 0) {
-+            break;
-+        }
-+    }
-+
-+    if (!bus || !bus->ops->register_companion) {
-+        qerror_report(QERR_INVALID_PARAMETER_VALUE, "masterbus",
-+                      "an USB masterbus");
-+        if (bus) {
-+            error_printf_unless_qmp(
-+                "USB bus '%s' does not allow companion controllers\n",
-+                masterbus);
-+        }
-+        return -1;
-+    }
-+
-+    for (i = 0; i < portcount; i++) {
-+        usb_fill_port(ports[i], opaque, i, ops, speedmask);
-+    }
-+
-+    return bus->ops->register_companion(bus, ports, portcount, firstport);
-+}
-+
- void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr)
- {
-     if (upstream) {
-diff --git a/hw/usb.h b/hw/usb.h
-index 076e2ff..a5f2efa 100644
---- a/hw/usb.h
-+++ b/hw/usb.h
-@@ -344,6 +344,8 @@ struct USBBus {
- };
- 
- struct USBBusOps {
-+    int (*register_companion)(USBBus *bus, USBPort *ports[],
-+                              uint32_t portcount, uint32_t firstport);
-     void (*device_destroy)(USBBus *bus, USBDevice *dev);
- };
- 
-@@ -356,6 +358,9 @@ USBDevice *usb_create_simple(USBBus *bus, const char *name);
- USBDevice *usbdevice_create(const char *cmdline);
- void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
-                        USBPortOps *ops, int speedmask);
-+int usb_register_companion(const char *masterbus, USBPort *ports[],
-+                           uint32_t portcount, uint32_t firstport,
-+                           void *opaque, USBPortOps *ops, int speedmask);
- void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr);
- void usb_unregister_port(USBBus *bus, USBPort *port);
- int usb_device_attach(USBDevice *dev);
--- 
-1.7.5.1
-
diff --git a/0005-char-Update-send_all-to-handle-nonblocking-chardev-w.patch b/0005-char-Update-send_all-to-handle-nonblocking-chardev-w.patch
new file mode 100644
index 0000000..ead1e8b
--- /dev/null
+++ b/0005-char-Update-send_all-to-handle-nonblocking-chardev-w.patch
@@ -0,0 +1,199 @@
+From 8aab343e17b05abb051105cdb367edb4deef0c60 Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 22:00:27 +0100
+Subject: [PATCH 05/13] char: Update send_all() to handle nonblocking chardev
+ write requests
+
+The send_all function is modified to return to the caller in case the
+driver cannot handle any more data.  It returns -EAGAIN or
+WSAEWOULDBLOCK on non-Windows and Windows platforms respectively.  This
+is only done when the caller sets a callback function handler indicating
+it's not interested in blocking till the driver has written out all the
+data.
+
+Currently there's no driver or caller that supports this.  Future
+commits will add such capability.
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+---
+ net/socket.c  |    4 +-
+ qemu-char.c   |   80 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
+ qemu_socket.h |    2 +-
+ 3 files changed, 77 insertions(+), 9 deletions(-)
+
+diff --git a/net/socket.c b/net/socket.c
+index bc1bf58..a40687a 100644
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -56,8 +56,8 @@ static ssize_t net_socket_receive(VLANClientState *nc, const uint8_t *buf, size_
+     uint32_t len;
+     len = htonl(size);
+ 
+-    send_all(s->fd, (const uint8_t *)&len, sizeof(len));
+-    return send_all(s->fd, buf, size);
++    send_all(NULL, s->fd, (const uint8_t *)&len, sizeof(len));
++    return send_all(NULL, s->fd, buf, size);
+ }
+ 
+ static ssize_t net_socket_receive_dgram(VLANClientState *nc, const uint8_t *buf, size_t size)
+diff --git a/qemu-char.c b/qemu-char.c
+index ec4eb68..8789627 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -513,7 +513,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
+ 
+ 
+ #ifdef _WIN32
+-int send_all(int fd, const void *buf, int len1)
++static int do_send(int fd, const void *buf, int len1, bool nonblock)
+ {
+     int ret, len;
+ 
+@@ -521,9 +521,14 @@ int send_all(int fd, const void *buf, int len1)
+     while (len > 0) {
+         ret = send(fd, buf, len, 0);
+         if (ret < 0) {
++            if (nonblock && len1 - len) {
++                return len1 - len;
++            }
+             errno = WSAGetLastError();
+             if (errno != WSAEWOULDBLOCK) {
+                 return -1;
++            } else if (errno == WSAEWOULDBLOCK && nonblock) {
++                return WSAEWOULDBLOCK;
+             }
+         } else if (ret == 0) {
+             break;
+@@ -537,7 +542,7 @@ int send_all(int fd, const void *buf, int len1)
+ 
+ #else
+ 
+-int send_all(int fd, const void *_buf, int len1)
++static int do_send(int fd, const void *_buf, int len1, bool nonblock)
+ {
+     int ret, len;
+     const uint8_t *buf = _buf;
+@@ -546,8 +551,15 @@ int send_all(int fd, const void *_buf, int len1)
+     while (len > 0) {
+         ret = write(fd, buf, len);
+         if (ret < 0) {
+-            if (errno != EINTR && errno != EAGAIN)
++            if (nonblock && len1 - len) {
++                return len1 - len;
++            }
++            if (errno == EAGAIN && nonblock) {
++                return -EAGAIN;
++            }
++            if (errno != EINTR && errno != EAGAIN) {
+                 return -1;
++            }
+         } else if (ret == 0) {
+             break;
+         } else {
+@@ -559,6 +571,55 @@ int send_all(int fd, const void *_buf, int len1)
+ }
+ #endif /* !_WIN32 */
+ 
++int send_all(CharDriverState *chr, int fd, const void *_buf, int len1)
++{
++    int ret, eagain_errno;
++    bool nonblock;
++
++    if (chr && chr->write_blocked) {
++        /*
++         * We don't handle this situation: the caller should not send
++         * us data while we're blocked.
++         *
++         * We could buffer this data here but that'll only encourage
++         * bad behaviour on part of the callers.
++         *
++         * Also, the data already in fd's buffers isn't easily
++         * migratable.  If we want full migration support, all the
++         * data landing here needs to be buffered and on migration,
++         * anything that's unsent needs to be transferred to the
++         * dest. machine (which again isn't a very good way of solving
++         * the problem, as the src may become writable just during
++         * migration and the reader could receive some data twice,
++         * essentially corrupting the data).
++         */
++        abort();
++    }
++
++    nonblock = false;
++    /*
++     * Ensure the char backend is able to receive and handle the
++     * 'write unblocked' event before we turn on nonblock support.
++     */
++    if (chr && chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) {
++        nonblock = true;
++    }
++    ret = do_send(fd, _buf, len1, nonblock);
++
++#ifdef _WIN32
++    eagain_errno = WSAEWOULDBLOCK;
++#else
++    eagain_errno = -EAGAIN;
++#endif
++
++    if (nonblock && (ret == eagain_errno || (ret >= 0 && ret < len1))) {
++        /* Update fd handler to wake up when chr becomes writable */
++        chr->chr_enable_write_fd_handler(chr);
++        chr->write_blocked = true;
++    }
++    return ret;
++}
++
+ #ifndef _WIN32
+ 
+ typedef struct {
+@@ -572,7 +633,7 @@ static int stdio_nb_clients = 0;
+ static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ {
+     FDCharDriver *s = chr->opaque;
+-    return send_all(s->fd_out, buf, len);
++    return send_all(chr, s->fd_out, buf, len);
+ }
+ 
+ static int fd_chr_read_poll(void *opaque)
+@@ -897,7 +958,7 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+         pty_chr_update_read_handler(chr);
+         return 0;
+     }
+-    return send_all(s->fd, buf, len);
++    return send_all(chr, s->fd, buf, len);
+ }
+ 
+ static int pty_chr_read_poll(void *opaque)
+@@ -1978,8 +2039,15 @@ static void tcp_closed(void *opaque)
+ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ {
+     TCPCharDriver *s = chr->opaque;
++
+     if (s->connected) {
+-        return send_all(s->fd, buf, len);
++        int ret;
++
++        ret = send_all(chr, s->fd, buf, len);
++        if (ret == -1 && errno == EPIPE) {
++            tcp_closed(chr);
++        }
++        return ret;
+     } else {
+         /* XXX: indicate an error ? */
+         return len;
+diff --git a/qemu_socket.h b/qemu_socket.h
+index 180e4db..6f453e5 100644
+--- a/qemu_socket.h
++++ b/qemu_socket.h
+@@ -36,7 +36,7 @@ int inet_aton(const char *cp, struct in_addr *ia);
+ int qemu_socket(int domain, int type, int protocol);
+ int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+ void socket_set_nonblock(int fd);
+-int send_all(int fd, const void *buf, int len1);
++int send_all(CharDriverState *chr, int fd, const void *buf, int len1);
+ 
+ /* New, ipv6-ready socket helper functions, see qemu-sockets.c */
+ int inet_listen_opts(QemuOpts *opts, int port_offset);
+-- 
+1.7.5.1
+
diff --git a/0005-usb-Make-port-wakeup-and-complete-ops-take-a-USBPort.patch b/0005-usb-Make-port-wakeup-and-complete-ops-take-a-USBPort.patch
deleted file mode 100644
index 9a30d18..0000000
--- a/0005-usb-Make-port-wakeup-and-complete-ops-take-a-USBPort.patch
+++ /dev/null
@@ -1,213 +0,0 @@
-From 99a493bf96aa03427633b24653112b43fa7b7131 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Tue, 21 Jun 2011 11:52:28 +0200
-Subject: [PATCH 05/35] usb: Make port wakeup and complete ops take a USBPort
- instead of a Device
-
-This makes them consistent with the attach and detach ops, and in general
-it makes sense to make portops take a port as argument. This also makes
-adding support for a companion controller easier / cleaner.
-
-[ kraxel: fix usb-musb.c build ]
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb-ehci.c |    2 +-
- hw/usb-hub.c  |   10 +++++-----
- hw/usb-musb.c |    6 +++---
- hw/usb-ohci.c |   12 +++++-------
- hw/usb-uhci.c |   11 +++++------
- hw/usb.c      |    4 ++--
- hw/usb.h      |    9 +++++++--
- 7 files changed, 28 insertions(+), 26 deletions(-)
-
-diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
-index 88cb2c2..428c90b 100644
---- a/hw/usb-ehci.c
-+++ b/hw/usb-ehci.c
-@@ -1111,7 +1111,7 @@ static int ehci_buffer_rw(EHCIQueue *q, int bytes, int rw)
-     return 0;
- }
- 
--static void ehci_async_complete_packet(USBDevice *dev, USBPacket *packet)
-+static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
- {
-     EHCIQueue *q = container_of(packet, EHCIQueue, packet);
- 
-diff --git a/hw/usb-hub.c b/hw/usb-hub.c
-index 6e2a358..d324bba 100644
---- a/hw/usb-hub.c
-+++ b/hw/usb-hub.c
-@@ -246,10 +246,10 @@ static void usb_hub_detach(USBPort *port1)
-     }
- }
- 
--static void usb_hub_wakeup(USBDevice *dev)
-+static void usb_hub_wakeup(USBPort *port1)
- {
--    USBHubState *s = dev->port->opaque;
--    USBHubPort *port = &s->ports[dev->port->index];
-+    USBHubState *s = port1->opaque;
-+    USBHubPort *port = &s->ports[port1->index];
- 
-     if (port->wPortStatus & PORT_STAT_SUSPEND) {
-         port->wPortChange |= PORT_STAT_C_SUSPEND;
-@@ -257,9 +257,9 @@ static void usb_hub_wakeup(USBDevice *dev)
-     }
- }
- 
--static void usb_hub_complete(USBDevice *dev, USBPacket *packet)
-+static void usb_hub_complete(USBPort *port, USBPacket *packet)
- {
--    USBHubState *s = dev->port->opaque;
-+    USBHubState *s = port->opaque;
- 
-     /*
-      * Just pass it along upstream for now.
-diff --git a/hw/usb-musb.c b/hw/usb-musb.c
-index 84e6017..580bdc8 100644
---- a/hw/usb-musb.c
-+++ b/hw/usb-musb.c
-@@ -261,7 +261,7 @@
- 
- static void musb_attach(USBPort *port);
- static void musb_detach(USBPort *port);
--static void musb_schedule_cb(USBDevice *dev, USBPacket *p);
-+static void musb_schedule_cb(USBPort *port, USBPacket *p);
- static void musb_device_destroy(USBBus *bus, USBDevice *dev);
- 
- static USBPortOps musb_port_ops = {
-@@ -517,7 +517,7 @@ static void musb_cb_tick1(void *opaque)
- 
- #define musb_cb_tick	(dir ? musb_cb_tick1 : musb_cb_tick0)
- 
--static void musb_schedule_cb(USBDevice *dev, USBPacket *packey)
-+static void musb_schedule_cb(USBPort *port, USBPacket *packey)
- {
-     MUSBPacket *p = container_of(packey, MUSBPacket, p);
-     MUSBEndPoint *ep = p->ep;
-@@ -615,7 +615,7 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
-     }
- 
-     ep->status[dir] = ret;
--    musb_schedule_cb(s->port.dev, &ep->packey[dir].p);
-+    musb_schedule_cb(&s->port, &ep->packey[dir].p);
- }
- 
- static void musb_tx_packet_complete(USBPacket *packey, void *opaque)
-diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
-index 95e4623..bd92c31 100644
---- a/hw/usb-ohci.c
-+++ b/hw/usb-ohci.c
-@@ -367,15 +367,13 @@ static void ohci_detach(USBPort *port1)
-         ohci_set_interrupt(s, OHCI_INTR_RHSC);
- }
- 
--static void ohci_wakeup(USBDevice *dev)
-+static void ohci_wakeup(USBPort *port1)
- {
--    USBBus *bus = usb_bus_from_device(dev);
--    OHCIState *s = container_of(bus, OHCIState, bus);
--    int portnum = dev->port->index;
--    OHCIPort *port = &s->rhport[portnum];
-+    OHCIState *s = port1->opaque;
-+    OHCIPort *port = &s->rhport[port1->index];
-     uint32_t intr = 0;
-     if (port->ctrl & OHCI_PORT_PSS) {
--        DPRINTF("usb-ohci: port %d: wakeup\n", portnum);
-+        DPRINTF("usb-ohci: port %d: wakeup\n", port1->index);
-         port->ctrl |= OHCI_PORT_PSSC;
-         port->ctrl &= ~OHCI_PORT_PSS;
-         intr = OHCI_INTR_RHSC;
-@@ -602,7 +600,7 @@ static void ohci_copy_iso_td(OHCIState *ohci,
- 
- static void ohci_process_lists(OHCIState *ohci, int completion);
- 
--static void ohci_async_complete_packet(USBDevice *dev, USBPacket *packet)
-+static void ohci_async_complete_packet(USBPort *port, USBPacket *packet)
- {
-     OHCIState *ohci = container_of(packet, OHCIState, usb_packet);
- #ifdef DEBUG_PACKET
-diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
-index fd25d2a..ab635f6 100644
---- a/hw/usb-uhci.c
-+++ b/hw/usb-uhci.c
-@@ -620,11 +620,10 @@ static void uhci_detach(USBPort *port1)
-     uhci_resume(s);
- }
- 
--static void uhci_wakeup(USBDevice *dev)
-+static void uhci_wakeup(USBPort *port1)
- {
--    USBBus *bus = usb_bus_from_device(dev);
--    UHCIState *s = container_of(bus, UHCIState, bus);
--    UHCIPort *port = s->ports + dev->port->index;
-+    UHCIState *s = port1->opaque;
-+    UHCIPort *port = &s->ports[port1->index];
- 
-     if (port->ctrl & UHCI_PORT_SUSPEND && !(port->ctrl & UHCI_PORT_RD)) {
-         port->ctrl |= UHCI_PORT_RD;
-@@ -657,7 +656,7 @@ static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
-     return ret;
- }
- 
--static void uhci_async_complete(USBDevice *dev, USBPacket *packet);
-+static void uhci_async_complete(USBPort *port, USBPacket *packet);
- static void uhci_process_frame(UHCIState *s);
- 
- /* return -1 if fatal error (frame must be stopped)
-@@ -849,7 +848,7 @@ done:
-     return len;
- }
- 
--static void uhci_async_complete(USBDevice *dev, USBPacket *packet)
-+static void uhci_async_complete(USBPort *port, USBPacket *packet)
- {
-     UHCIAsync *async = container_of(packet, UHCIAsync, packet);
-     UHCIState *s = async->uhci;
-diff --git a/hw/usb.c b/hw/usb.c
-index 4a39cbc..735ffd1 100644
---- a/hw/usb.c
-+++ b/hw/usb.c
-@@ -52,7 +52,7 @@ void usb_attach(USBPort *port, USBDevice *dev)
- void usb_wakeup(USBDevice *dev)
- {
-     if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) {
--        dev->port->ops->wakeup(dev);
-+        dev->port->ops->wakeup(dev->port);
-     }
- }
- 
-@@ -335,7 +335,7 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p)
- {
-     /* Note: p->owner != dev is possible in case dev is a hub */
-     assert(p->owner != NULL);
--    dev->port->ops->complete(dev, p);
-+    dev->port->ops->complete(dev->port, p);
-     p->owner = NULL;
- }
- 
-diff --git a/hw/usb.h b/hw/usb.h
-index a5f2efa..65f45a0 100644
---- a/hw/usb.h
-+++ b/hw/usb.h
-@@ -252,8 +252,13 @@ struct USBDeviceInfo {
- typedef struct USBPortOps {
-     void (*attach)(USBPort *port);
-     void (*detach)(USBPort *port);
--    void (*wakeup)(USBDevice *dev);
--    void (*complete)(USBDevice *dev, USBPacket *p);
-+    void (*wakeup)(USBPort *port);
-+    /*
-+     * Note that port->dev will be different then the device from which
-+     * the packet originated when a hub is involved, if you want the orginating
-+     * device use p->owner
-+     */
-+    void (*complete)(USBPort *port, USBPacket *p);
- } USBPortOps;
- 
- /* USB port on which a device can be connected */
--- 
-1.7.5.1
-
diff --git a/0006-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch b/0006-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch
new file mode 100644
index 0000000..d8fcefc
--- /dev/null
+++ b/0006-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch
@@ -0,0 +1,81 @@
+From 9a773de6f770bf2f05acca786e14abd79a9f930c Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 22:02:47 +0100
+Subject: [PATCH 06/13] char: Equip the unix/tcp backend to handle nonblocking
+ writes#
+
+Now that the infrastructure is in place to return -EAGAIN to callers,
+individual char drivers can set their update_fd_handlers() function to
+set or remove an fd's write handler.  This handler checks if the driver
+became writable.
+
+A generic callback routine is used for unblocking writes and letting
+users of chardevs know that a driver became writable again.
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+---
+ qemu-char.c |   34 ++++++++++++++++++++++++++++++++++
+ 1 files changed, 34 insertions(+), 0 deletions(-)
+
+diff --git a/qemu-char.c b/qemu-char.c
+index 8789627..d811f2a 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -106,6 +106,19 @@
+ static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
+     QTAILQ_HEAD_INITIALIZER(chardevs);
+ 
++/*
++ * Generic routine that gets called when chardev becomes writable.
++ * Lets chardev user know it's OK to send more data.
++ */
++static void char_write_unblocked(void *opaque)
++{
++    CharDriverState *chr = opaque;
++
++    chr->write_blocked = false;
++    chr->chr_disable_write_fd_handler(chr);
++    chr->chr_write_unblocked(chr->handler_opaque);
++}
++
+ static void qemu_chr_event(CharDriverState *s, int event)
+ {
+     /* Keep track if the char device is open */
+@@ -2308,6 +2321,25 @@ static void tcp_chr_close(CharDriverState *chr)
+     qemu_chr_event(chr, CHR_EVENT_CLOSED);
+ }
+ 
++static void tcp_enable_write_fd_handler(CharDriverState *chr)
++{
++    TCPCharDriver *s = chr->opaque;
++
++    /*
++     * This function is called only after tcp_chr_connect() is called
++     * (either in 'server' mode or client mode.  So we're sure of
++     * s->fd being initialised.
++     */
++    enable_write_fd_handler(s->fd, char_write_unblocked);
++}
++
++static void tcp_disable_write_fd_handler(CharDriverState *chr)
++{
++    TCPCharDriver *s = chr->opaque;
++
++    disable_write_fd_handler(s->fd);
++}
++
+ static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr)
+ {
+     CharDriverState *chr = NULL;
+@@ -2364,6 +2396,8 @@ static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr)
+     chr->chr_close = tcp_chr_close;
+     chr->get_msgfd = tcp_get_msgfd;
+     chr->chr_add_client = tcp_chr_add_client;
++    chr->chr_enable_write_fd_handler = tcp_enable_write_fd_handler;
++    chr->chr_disable_write_fd_handler = tcp_disable_write_fd_handler;
+ 
+     if (is_listen) {
+         s->listen_fd = fd;
+-- 
+1.7.5.1
+
diff --git a/0006-usb-Replace-device_destroy-bus-op-with-a-child_detac.patch b/0006-usb-Replace-device_destroy-bus-op-with-a-child_detac.patch
deleted file mode 100644
index 5811b96..0000000
--- a/0006-usb-Replace-device_destroy-bus-op-with-a-child_detac.patch
+++ /dev/null
@@ -1,358 +0,0 @@
-From a0f20940be744556be844ac857fa6dd679dc7af0 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Fri, 24 Jun 2011 12:31:11 +0200
-Subject: [PATCH 06/35] usb: Replace device_destroy bus op with a child_detach
- port op
-
-Note this fixes 2 things in one go, first of all the device_destroy bus
-op should be a device_detach bus op, as pending async packets from the
-device should be cancelled on detach not on destroy.
-
-Secondly having this as a bus op won't work with companion controllers, since
-then there will be 1 bus driven by the ehci controller and thus 1 set of bus
-ops, but the device being detached may be downstream of a handed over port.
-Making the detach of a downstream device a port op allows the ehci controller
-to forward this to the companion controller port for handed over ports.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/milkymist-softusb.c |    9 +++++++--
- hw/usb-bus.c           |    2 --
- hw/usb-ehci.c          |   18 ++++++++++--------
- hw/usb-hub.c           |   12 ++++++++++++
- hw/usb-musb.c          |   17 +++++++++++++----
- hw/usb-ohci.c          |   16 ++++++++++++----
- hw/usb-uhci.c          |   18 ++++++++++--------
- hw/usb.h               |    6 +++++-
- 8 files changed, 69 insertions(+), 29 deletions(-)
-
-diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c
-index 5ab35c3..ce2bfc6 100644
---- a/hw/milkymist-softusb.c
-+++ b/hw/milkymist-softusb.c
-@@ -247,16 +247,21 @@ static void softusb_attach(USBPort *port)
- {
- }
- 
--static void softusb_device_destroy(USBBus *bus, USBDevice *dev)
-+static void softusb_detach(USBPort *port)
-+{
-+}
-+
-+static void softusb_child_detach(USBPort *port, USBDevice *child)
- {
- }
- 
- static USBPortOps softusb_ops = {
-     .attach = softusb_attach,
-+    .detach = softusb_detach,
-+    .child_detach = softusb_child_detach,
- };
- 
- static USBBusOps softusb_bus_ops = {
--    .device_destroy = softusb_device_destroy,
- };
- 
- static void milkymist_softusb_reset(DeviceState *d)
-diff --git a/hw/usb-bus.c b/hw/usb-bus.c
-index b511bac..c8347e9 100644
---- a/hw/usb-bus.c
-+++ b/hw/usb-bus.c
-@@ -82,12 +82,10 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
- static int usb_qdev_exit(DeviceState *qdev)
- {
-     USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
--    USBBus *bus = usb_bus_from_device(dev);
- 
-     if (dev->attached) {
-         usb_device_detach(dev);
-     }
--    bus->ops->device_destroy(bus, dev);
-     if (dev->info->handle_destroy) {
-         dev->info->handle_destroy(dev);
-     }
-diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
-index 428c90b..96451f3 100644
---- a/hw/usb-ehci.c
-+++ b/hw/usb-ehci.c
-@@ -751,6 +751,8 @@ static void ehci_detach(USBPort *port)
- 
-     trace_usb_ehci_port_detach(port->index);
- 
-+    ehci_queues_rip_device(s, port->dev);
-+
-     *portsc &= ~PORTSC_CONNECT;
-     *portsc |= PORTSC_CSC;
- 
-@@ -764,6 +766,13 @@ static void ehci_detach(USBPort *port)
-     }
- }
- 
-+static void ehci_child_detach(USBPort *port, USBDevice *child)
-+{
-+    EHCIState *s = port->opaque;
-+
-+    ehci_queues_rip_device(s, child);
-+}
-+
- /* 4.1 host controller initialization */
- static void ehci_reset(void *opaque)
- {
-@@ -2117,23 +2126,16 @@ static void ehci_map(PCIDevice *pci_dev, int region_num,
-     cpu_register_physical_memory(addr, size, s->mem);
- }
- 
--static void ehci_device_destroy(USBBus *bus, USBDevice *dev)
--{
--    EHCIState *s = container_of(bus, EHCIState, bus);
--
--    ehci_queues_rip_device(s, dev);
--}
--
- static int usb_ehci_initfn(PCIDevice *dev);
- 
- static USBPortOps ehci_port_ops = {
-     .attach = ehci_attach,
-     .detach = ehci_detach,
-+    .child_detach = ehci_child_detach,
-     .complete = ehci_async_complete_packet,
- };
- 
- static USBBusOps ehci_bus_ops = {
--    .device_destroy = ehci_device_destroy,
- };
- 
- static PCIDeviceInfo ehci_info = {
-diff --git a/hw/usb-hub.c b/hw/usb-hub.c
-index d324bba..b7557ce 100644
---- a/hw/usb-hub.c
-+++ b/hw/usb-hub.c
-@@ -238,6 +238,9 @@ static void usb_hub_detach(USBPort *port1)
-     USBHubState *s = port1->opaque;
-     USBHubPort *port = &s->ports[port1->index];
- 
-+    /* Let upstream know the device on this port is gone */
-+    s->dev.port->ops->child_detach(s->dev.port, port1->dev);
-+
-     port->wPortStatus &= ~PORT_STAT_CONNECTION;
-     port->wPortChange |= PORT_STAT_C_CONNECTION;
-     if (port->wPortStatus & PORT_STAT_ENABLE) {
-@@ -246,6 +249,14 @@ static void usb_hub_detach(USBPort *port1)
-     }
- }
- 
-+static void usb_hub_child_detach(USBPort *port1, USBDevice *child)
-+{
-+    USBHubState *s = port1->opaque;
-+
-+    /* Pass along upstream */
-+    s->dev.port->ops->child_detach(s->dev.port, child);
-+}
-+
- static void usb_hub_wakeup(USBPort *port1)
- {
-     USBHubState *s = port1->opaque;
-@@ -537,6 +548,7 @@ static void usb_hub_handle_destroy(USBDevice *dev)
- static USBPortOps usb_hub_port_ops = {
-     .attach = usb_hub_attach,
-     .detach = usb_hub_detach,
-+    .child_detach = usb_hub_child_detach,
-     .wakeup = usb_hub_wakeup,
-     .complete = usb_hub_complete,
- };
-diff --git a/hw/usb-musb.c b/hw/usb-musb.c
-index 580bdc8..035dda8 100644
---- a/hw/usb-musb.c
-+++ b/hw/usb-musb.c
-@@ -261,17 +261,18 @@
- 
- static void musb_attach(USBPort *port);
- static void musb_detach(USBPort *port);
-+static void musb_child_detach(USBPort *port, USBDevice *child);
- static void musb_schedule_cb(USBPort *port, USBPacket *p);
--static void musb_device_destroy(USBBus *bus, USBDevice *dev);
-+static void musb_async_cancel_device(MUSBState *s, USBDevice *dev);
- 
- static USBPortOps musb_port_ops = {
-     .attach = musb_attach,
-     .detach = musb_detach,
-+    .child_detach = musb_child_detach,
-     .complete = musb_schedule_cb,
- };
- 
- static USBBusOps musb_bus_ops = {
--    .device_destroy = musb_device_destroy,
- };
- 
- typedef struct MUSBPacket MUSBPacket;
-@@ -497,10 +498,19 @@ static void musb_detach(USBPort *port)
- {
-     MUSBState *s = (MUSBState *) port->opaque;
- 
-+    musb_async_cancel_device(s, port->dev);
-+
-     musb_intr_set(s, musb_irq_disconnect, 1);
-     musb_session_update(s, 1, s->session);
- }
- 
-+static void musb_child_detach(USBPort *port, USBDevice *child)
-+{
-+    MUSBState *s = (MUSBState *) port->opaque;
-+
-+    musb_async_cancel_device(s, child);
-+}
-+
- static void musb_cb_tick0(void *opaque)
- {
-     MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
-@@ -782,9 +792,8 @@ static void musb_rx_packet_complete(USBPacket *packey, void *opaque)
-     musb_rx_intr_set(s, epnum, 1);
- }
- 
--static void musb_device_destroy(USBBus *bus, USBDevice *dev)
-+static void musb_async_cancel_device(MUSBState *s, USBDevice *dev)
- {
--    MUSBState *s = container_of(bus, MUSBState, bus);
-     int ep, dir;
- 
-     for (ep = 0; ep < 16; ep++) {
-diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
-index bd92c31..46f0bcb 100644
---- a/hw/usb-ohci.c
-+++ b/hw/usb-ohci.c
-@@ -124,6 +124,7 @@ struct ohci_hcca {
- };
- 
- static void ohci_bus_stop(OHCIState *ohci);
-+static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev);
- 
- /* Bitfields for the first word of an Endpoint Desciptor.  */
- #define OHCI_ED_FA_SHIFT  0
-@@ -351,6 +352,8 @@ static void ohci_detach(USBPort *port1)
-     OHCIPort *port = &s->rhport[port1->index];
-     uint32_t old_state = port->ctrl;
- 
-+    ohci_async_cancel_device(s, port1->dev);
-+
-     /* set connect status */
-     if (port->ctrl & OHCI_PORT_CCS) {
-         port->ctrl &= ~OHCI_PORT_CCS;
-@@ -392,6 +395,13 @@ static void ohci_wakeup(USBPort *port1)
-     ohci_set_interrupt(s, intr);
- }
- 
-+static void ohci_child_detach(USBPort *port1, USBDevice *child)
-+{
-+    OHCIState *s = port1->opaque;
-+
-+    ohci_async_cancel_device(s, child);
-+}
-+
- /* Reset the controller */
- static void ohci_reset(void *opaque)
- {
-@@ -1673,10 +1683,8 @@ static void ohci_mem_write(void *ptr, target_phys_addr_t addr, uint32_t val)
-     }
- }
- 
--static void ohci_device_destroy(USBBus *bus, USBDevice *dev)
-+static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
- {
--    OHCIState *ohci = container_of(bus, OHCIState, bus);
--
-     if (ohci->async_td && ohci->usb_packet.owner == dev) {
-         usb_cancel_packet(&ohci->usb_packet);
-         ohci->async_td = 0;
-@@ -1700,12 +1708,12 @@ static CPUWriteMemoryFunc * const ohci_writefn[3]={
- static USBPortOps ohci_port_ops = {
-     .attach = ohci_attach,
-     .detach = ohci_detach,
-+    .child_detach = ohci_child_detach,
-     .wakeup = ohci_wakeup,
-     .complete = ohci_async_complete_packet,
- };
- 
- static USBBusOps ohci_bus_ops = {
--    .device_destroy = ohci_device_destroy,
- };
- 
- static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
-diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
-index ab635f6..a46d61a 100644
---- a/hw/usb-uhci.c
-+++ b/hw/usb-uhci.c
-@@ -606,6 +606,8 @@ static void uhci_detach(USBPort *port1)
-     UHCIState *s = port1->opaque;
-     UHCIPort *port = &s->ports[port1->index];
- 
-+    uhci_async_cancel_device(s, port1->dev);
-+
-     /* set connect status */
-     if (port->ctrl & UHCI_PORT_CCS) {
-         port->ctrl &= ~UHCI_PORT_CCS;
-@@ -620,6 +622,13 @@ static void uhci_detach(USBPort *port1)
-     uhci_resume(s);
- }
- 
-+static void uhci_child_detach(USBPort *port1, USBDevice *child)
-+{
-+    UHCIState *s = port1->opaque;
-+
-+    uhci_async_cancel_device(s, child);
-+}
-+
- static void uhci_wakeup(USBPort *port1)
- {
-     UHCIState *s = port1->opaque;
-@@ -1095,22 +1104,15 @@ static void uhci_map(PCIDevice *pci_dev, int region_num,
-     register_ioport_read(addr, 32, 1, uhci_ioport_readb, s);
- }
- 
--static void uhci_device_destroy(USBBus *bus, USBDevice *dev)
--{
--    UHCIState *s = container_of(bus, UHCIState, bus);
--
--    uhci_async_cancel_device(s, dev);
--}
--
- static USBPortOps uhci_port_ops = {
-     .attach = uhci_attach,
-     .detach = uhci_detach,
-+    .child_detach = uhci_child_detach,
-     .wakeup = uhci_wakeup,
-     .complete = uhci_async_complete,
- };
- 
- static USBBusOps uhci_bus_ops = {
--    .device_destroy = uhci_device_destroy,
- };
- 
- static int usb_uhci_common_initfn(PCIDevice *dev)
-diff --git a/hw/usb.h b/hw/usb.h
-index 65f45a0..ded2de2 100644
---- a/hw/usb.h
-+++ b/hw/usb.h
-@@ -252,6 +252,11 @@ struct USBDeviceInfo {
- typedef struct USBPortOps {
-     void (*attach)(USBPort *port);
-     void (*detach)(USBPort *port);
-+    /*
-+     * This gets called when a device downstream from the device attached to
-+     * the port (iow attached through a hub) gets detached.
-+     */
-+    void (*child_detach)(USBPort *port, USBDevice *child);
-     void (*wakeup)(USBPort *port);
-     /*
-      * Note that port->dev will be different then the device from which
-@@ -351,7 +356,6 @@ struct USBBus {
- struct USBBusOps {
-     int (*register_companion)(USBBus *bus, USBPort *ports[],
-                               uint32_t portcount, uint32_t firstport);
--    void (*device_destroy)(USBBus *bus, USBDevice *dev);
- };
- 
- void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host);
--- 
-1.7.5.1
-
diff --git a/0007-char-Throttle-when-host-connection-is-down.patch b/0007-char-Throttle-when-host-connection-is-down.patch
new file mode 100644
index 0000000..edfd98e
--- /dev/null
+++ b/0007-char-Throttle-when-host-connection-is-down.patch
@@ -0,0 +1,56 @@
+From 7e19009aa497ae5bc2da8dfedb956f8a705698f1 Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 22:05:10 +0100
+Subject: [PATCH 07/13] char: Throttle when host connection is down#
+
+When the host-side connection goes down, throttle the virtio-serial bus
+and later unthrottle when a connection gets established.  This helps
+prevent any lost IO (guest->host) while the host connection was down.
+
+Bugzilla: 621484
+
+This commit actually helps the bug mentioned above as no writes will now
+get lost because of the throttling done here.  With just the patches
+sent earlier for that bug, one write will end up getting lost in the
+worst case (host d/c, guest write, host connect).
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+---
+ qemu-char.c |   14 ++++++++++++++
+ 1 files changed, 14 insertions(+), 0 deletions(-)
+
+diff --git a/qemu-char.c b/qemu-char.c
+index d811f2a..111fdc8 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -140,6 +140,9 @@ static void qemu_chr_generic_open_bh(void *opaque)
+ {
+     CharDriverState *s = opaque;
+     qemu_chr_event(s, CHR_EVENT_OPENED);
++    if (s->write_blocked) {
++        char_write_unblocked(s);
++    }
+     qemu_bh_delete(s->bh);
+     s->bh = NULL;
+ }
+@@ -2059,6 +2062,17 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+         ret = send_all(chr, s->fd, buf, len);
+         if (ret == -1 && errno == EPIPE) {
+             tcp_closed(chr);
++
++            if (chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) {
++                /*
++                 * Since we haven't written out anything, let's say
++                 * we're throttled.  This will prevent any output from
++                 * the guest getting lost if host-side chardev goes
++                 * down.  Unthrottle when we re-connect.
++                 */
++                chr->write_blocked = true;
++                return 0;
++            }
+         }
+         return ret;
+     } else {
+-- 
+1.7.5.1
+
diff --git a/0007-usb-ehci-drop-unused-num-ports-state-member.patch b/0007-usb-ehci-drop-unused-num-ports-state-member.patch
deleted file mode 100644
index 7ea28e7..0000000
--- a/0007-usb-ehci-drop-unused-num-ports-state-member.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 788de57b67ba5e14d965edb542eb58ed4603faf8 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Fri, 17 Jun 2011 15:26:29 +0200
-Subject: [PATCH 07/35] usb-ehci: drop unused num-ports state member
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb-ehci.c |    1 -
- 1 files changed, 0 insertions(+), 1 deletions(-)
-
-diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
-index 96451f3..87e1de3 100644
---- a/hw/usb-ehci.c
-+++ b/hw/usb-ehci.c
-@@ -373,7 +373,6 @@ struct EHCIState {
-     qemu_irq irq;
-     target_phys_addr_t mem_base;
-     int mem;
--    int num_ports;
- 
-     /* properties */
-     uint32_t freq;
--- 
-1.7.5.1
-
diff --git a/0008-usb-ehci-Connect-Status-bit-is-read-only-don-t-allow.patch b/0008-usb-ehci-Connect-Status-bit-is-read-only-don-t-allow.patch
deleted file mode 100644
index 7ebbdaf..0000000
--- a/0008-usb-ehci-Connect-Status-bit-is-read-only-don-t-allow.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From f7e7c102ed1c3ff7790c84f8bb9d379ad6405d6b Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Tue, 21 Jun 2011 12:12:35 +0200
-Subject: [PATCH 08/35] usb-ehci: Connect Status bit is read only, don't allow
- changing it by the guest
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb-ehci.c |    4 ++--
- 1 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
-index 87e1de3..ce1a432 100644
---- a/hw/usb-ehci.c
-+++ b/hw/usb-ehci.c
-@@ -103,10 +103,10 @@
- #define PORTSC_BEGIN         PORTSC
- #define PORTSC_END           (PORTSC + 4 * NB_PORTS)
- /*
-- * Bits that are reserverd or are read-only are masked out of values
-+ * Bits that are reserved or are read-only are masked out of values
-  * written to us by software
-  */
--#define PORTSC_RO_MASK       0x007021c5
-+#define PORTSC_RO_MASK       0x007021c4
- #define PORTSC_RWC_MASK      0x0000002a
- #define PORTSC_WKOC_E        (1 << 22)    // Wake on Over Current Enable
- #define PORTSC_WKDS_E        (1 << 21)    // Wake on Disconnect Enable
--- 
-1.7.5.1
-
diff --git a/0008-virtio-console-Enable-port-throttling-when-chardev-i.patch b/0008-virtio-console-Enable-port-throttling-when-chardev-i.patch
new file mode 100644
index 0000000..a3c07df
--- /dev/null
+++ b/0008-virtio-console-Enable-port-throttling-when-chardev-i.patch
@@ -0,0 +1,49 @@
+From badc85629db4d774f3b5b41070474bd5479d5be3 Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 22:06:41 +0100
+Subject: [PATCH 08/13] virtio-console: Enable port throttling when chardev is
+ slow to consume data
+
+When a chardev indicates it can't accept more data, we tell the
+virtio-serial code to stop sending us any more data till we tell
+otherwise.  This helps in guests continuing to run normally while the vq
+keeps getting full and eventually the guest stops queueing more data.
+As soon as the chardev indicates it can accept more data, start pushing!
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+---
+ hw/virtio-console.c |   11 +++++++++++
+ 1 files changed, 11 insertions(+), 0 deletions(-)
+
+diff --git a/hw/virtio-console.c b/hw/virtio-console.c
+index cfc3087..b91f46e 100644
+--- a/hw/virtio-console.c
++++ b/hw/virtio-console.c
+@@ -20,6 +20,16 @@ typedef struct VirtConsole {
+     CharDriverState *chr;
+ } VirtConsole;
+ 
++/*
++ * Callback function that's called from chardevs when backend becomes
++ * writable.
++ */
++static void chr_write_unblocked(void *opaque)
++{
++    VirtConsole *vcon = opaque;
++
++    virtio_serial_throttle_port(&vcon->port, false);
++}
+ 
+ /* Callback function that's called when the guest sends us data */
+ static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
+@@ -99,6 +109,7 @@ static const QemuChrHandlers chr_handlers = {
+     .fd_can_read = chr_can_read,
+     .fd_read = chr_read,
+     .fd_event = chr_event,
++    .fd_write_unblocked = chr_write_unblocked,
+ };
+ 
+ static int virtconsole_initfn(VirtIOSerialPort *port)
+-- 
+1.7.5.1
+
diff --git a/0009-spice-qemu-char.c-add-throttling.patch b/0009-spice-qemu-char.c-add-throttling.patch
new file mode 100644
index 0000000..7c2b68b
--- /dev/null
+++ b/0009-spice-qemu-char.c-add-throttling.patch
@@ -0,0 +1,133 @@
+From 433a034b4ee87fe228be4e7f7e4399101d1e33c8 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy@redhat.com>
+Date: Tue, 22 Mar 2011 12:27:59 +0200
+Subject: [PATCH 09/13] spice-qemu-char.c: add throttling
+
+BZ: 672191
+
+upstream: not submitted (explained below)
+
+Adds throttling support to spicevmc chardev. Uses a timer to avoid recursing:
+1. spice-server: reds.c:            read_from_vdi_port
+2. qemu:         spice-qemu-char.c: vmc_read
+3.                                  chr_write_unblocked
+                                (calls virtio_serial_throttle_port(port, false))
+4. qemu:         virtio ...
+5. qemu:         spice-qemu-char.c: spice_chr_write
+6. qemu:         spice-qemu-char.c: wakeup (calls into spice-server)
+7. spice-server: ...
+8. qemu:         spice-qemu-char.c: vmc_read
+
+Instead, in vmc_read if we were throttled and we are just about to return
+all the bytes we will set a timer to be triggered immediately to call
+chr_write_unblocked. Then we return after 2 above, and 3 is called from the
+timer callback. This also means we can later remove some ugly recursion protection
+from spice-server.
+
+The other tricky point in this patch is not returning the leftover chunk twice.
+When we throttle, by definition we have data that spice server didn't consume.
+It is being kept by virtio-serial, and by us. The next vmc_read callback needs
+to not return it, but just do unthrottling. Then virtio will give us the remaining
+chunk as usual in spice_chr_write, and we will pass it to spice server in the
+next vmc_read.
+
+This patch relies on Amit's series to expose throttling to chardev's, which
+was not accepted upstream, and will not be accepted upstream until the mainloop
+is reworked to use glib.
+---
+ spice-qemu-char.c |   39 +++++++++++++++++++++++++++++++++++----
+ 1 files changed, 35 insertions(+), 4 deletions(-)
+
+diff --git a/spice-qemu-char.c b/spice-qemu-char.c
+index 95bf6b6..0f72e91 100644
+--- a/spice-qemu-char.c
++++ b/spice-qemu-char.c
+@@ -1,4 +1,6 @@
+ #include "config-host.h"
++#include "qemu-common.h"
++#include "qemu-timer.h"
+ #include "trace.h"
+ #include "ui/qemu-spice.h"
+ #include <spice.h>
+@@ -25,6 +27,7 @@ typedef struct SpiceCharDriver {
+     uint8_t               *datapos;
+     ssize_t               bufsize, datalen;
+     uint32_t              debug;
++    QEMUTimer             *unblock_timer;
+ } SpiceCharDriver;
+ 
+ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
+@@ -50,6 +53,17 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
+     return out;
+ }
+ 
++static void spice_chr_unblock(void *opaque)
++{
++    SpiceCharDriver *scd = opaque;
++
++    if (scd->chr->chr_write_unblocked == NULL) {
++        dprintf(scd, 1, "%s: backend doesn't support unthrottling.\n", __func__);
++        return;
++    }
++    scd->chr->chr_write_unblocked(scd->chr->handler_opaque);
++}
++
+ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
+ {
+     SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
+@@ -61,9 +75,16 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
+         scd->datapos += bytes;
+         scd->datalen -= bytes;
+         assert(scd->datalen >= 0);
+-        if (scd->datalen == 0) {
+-            scd->datapos = 0;
+-        }
++    }
++    if (scd->datalen == 0 && scd->chr->write_blocked) {
++        dprintf(scd, 1, "%s: unthrottling (%d)\n", __func__, bytes);
++        scd->chr->write_blocked = false;
++        /*
++         * set a timer instead of calling scd->chr->chr_write_unblocked directly,
++         * because that will call back into spice_chr_write (see
++         * virtio-console.c:chr_write_unblocked), which is unwanted.
++         */
++        qemu_mod_timer(scd->unblock_timer, 0);
+     }
+     trace_spice_vmc_read(bytes, len);
+     return bytes;
+@@ -106,6 +127,7 @@ static void vmc_unregister_interface(SpiceCharDriver *scd)
+ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ {
+     SpiceCharDriver *s = chr->opaque;
++    int read_bytes;
+ 
+     dprintf(s, 2, "%s: %d\n", __func__, len);
+     vmc_register_interface(s);
+@@ -118,7 +140,15 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+     s->datapos = s->buffer;
+     s->datalen = len;
+     spice_server_char_device_wakeup(&s->sin);
+-    return len;
++    read_bytes = len - s->datalen;
++    if (read_bytes != len) {
++        dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__,
++                read_bytes, len, s->bufsize);
++        s->chr->write_blocked = true;
++        /* We'll get passed in the unconsumed data with the next call */
++        s->datalen = 0;
++    }
++    return read_bytes;
+ }
+ 
+ static void spice_chr_close(struct CharDriverState *chr)
+@@ -196,6 +226,7 @@ int qemu_chr_open_spice(QemuOpts *opts, CharDriverState **_chr)
+     chr->chr_close = spice_chr_close;
+     chr->chr_guest_open = spice_chr_guest_open;
+     chr->chr_guest_close = spice_chr_guest_close;
++    s->unblock_timer = qemu_new_timer_ms(vm_clock, spice_chr_unblock, s);
+ 
+     qemu_chr_generic_open(chr);
+ 
+-- 
+1.7.5.1
+
diff --git a/0009-usb-ehci-cleanup-port-reset-handling.patch b/0009-usb-ehci-cleanup-port-reset-handling.patch
deleted file mode 100644
index 2651396..0000000
--- a/0009-usb-ehci-cleanup-port-reset-handling.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From afada27ad05658aae93aa8beab34b1b6885f63b9 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Tue, 21 Jun 2011 12:23:40 +0200
-Subject: [PATCH 09/35] usb-ehci: cleanup port reset handling
-
-Doing a usb_attach when dev is NULL will just result in the
-port detach op getting called even though nothing was connected in
-the first place.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb-ehci.c |    7 +------
- 1 files changed, 1 insertions(+), 6 deletions(-)
-
-diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
-index ce1a432..d85e0a9 100644
---- a/hw/usb-ehci.c
-+++ b/hw/usb-ehci.c
-@@ -863,14 +863,9 @@ static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
- 
-     if (!(val & PORTSC_PRESET) &&(*portsc & PORTSC_PRESET)) {
-         trace_usb_ehci_port_reset(port, 0);
--        usb_attach(&s->ports[port], dev);
--
--        // TODO how to handle reset of ports with no device
-         if (dev) {
-+            usb_attach(&s->ports[port], dev);
-             usb_send_msg(dev, USB_MSG_RESET);
--        }
--
--        if (s->ports[port].dev) {
-             *portsc &= ~PORTSC_CSC;
-         }
- 
--- 
-1.7.5.1
-
diff --git a/0010-spice-qemu-char.c-remove-intermediate-buffer.patch b/0010-spice-qemu-char.c-remove-intermediate-buffer.patch
new file mode 100644
index 0000000..3999246
--- /dev/null
+++ b/0010-spice-qemu-char.c-remove-intermediate-buffer.patch
@@ -0,0 +1,71 @@
+From 7735740bd0c9f2d9585c64cc5f975dd03f2a7c11 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy@redhat.com>
+Date: Tue, 22 Mar 2011 12:28:00 +0200
+Subject: [PATCH 10/13] spice-qemu-char.c: remove intermediate buffer
+
+BZ: 672191
+upstream: not submitted (explained below)
+
+virtio-serial's buffer is valid when it calls us, and we don't
+access it otherwise: vmc_read is only called in response to wakeup,
+or else we set datalen=0 and throttle. Then vmc_read is called back,
+we return 0 (not accessing the buffer) and set the timer to unthrottle.
+
+Also make datalen int and not ssize_t (to fit spice_chr_write signature).
+
+This relied on the previous patch that introduces throttling, which
+can't go upstream right now as explained in that patch.
+---
+ spice-qemu-char.c |   18 ++++++------------
+ 1 files changed, 6 insertions(+), 12 deletions(-)
+
+diff --git a/spice-qemu-char.c b/spice-qemu-char.c
+index 0f72e91..2b8aec4 100644
+--- a/spice-qemu-char.c
++++ b/spice-qemu-char.c
+@@ -23,9 +23,8 @@ typedef struct SpiceCharDriver {
+     SpiceCharDeviceInstance     sin;
+     char                  *subtype;
+     bool                  active;
+-    uint8_t               *buffer;
+-    uint8_t               *datapos;
+-    ssize_t               bufsize, datalen;
++    const uint8_t         *datapos;
++    int                   datalen;
+     uint32_t              debug;
+     QEMUTimer             *unblock_timer;
+ } SpiceCharDriver;
+@@ -69,7 +68,7 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
+     SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
+     int bytes = MIN(len, scd->datalen);
+ 
+-    dprintf(scd, 2, "%s: %p %d/%d/%zd\n", __func__, scd->datapos, len, bytes, scd->datalen);
++    dprintf(scd, 2, "%s: %p %d/%d/%d\n", __func__, scd->datapos, len, bytes, scd->datalen);
+     if (bytes > 0) {
+         memcpy(buf, scd->datapos, bytes);
+         scd->datapos += bytes;
+@@ -132,18 +131,13 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+     dprintf(s, 2, "%s: %d\n", __func__, len);
+     vmc_register_interface(s);
+     assert(s->datalen == 0);
+-    if (s->bufsize < len) {
+-        s->bufsize = len;
+-        s->buffer = qemu_realloc(s->buffer, s->bufsize);
+-    }
+-    memcpy(s->buffer, buf, len);
+-    s->datapos = s->buffer;
++    s->datapos = buf;
+     s->datalen = len;
+     spice_server_char_device_wakeup(&s->sin);
+     read_bytes = len - s->datalen;
+     if (read_bytes != len) {
+-        dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__,
+-                read_bytes, len, s->bufsize);
++        dprintf(s, 1, "%s: throttling: %d < %d\n", __func__,
++                read_bytes, len);
+         s->chr->write_blocked = true;
+         /* We'll get passed in the unconsumed data with the next call */
+         s->datalen = 0;
+-- 
+1.7.5.1
+
diff --git a/0010-usb-assert-on-calling-usb_attach-port-NULL-on-a-port.patch b/0010-usb-assert-on-calling-usb_attach-port-NULL-on-a-port.patch
deleted file mode 100644
index 8b86aed..0000000
--- a/0010-usb-assert-on-calling-usb_attach-port-NULL-on-a-port.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From a7466b2ff8e1cbdf3abf08a935c3b6c19303ffc2 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Fri, 24 Jun 2011 14:26:18 +0200
-Subject: [PATCH 10/35] usb: assert on calling usb_attach(port, NULL) on a
- port without a dev
-
-with the "usb-ehci: cleanup port reset handling" patch in place no callers
-are calling usb_attach(port, NULL) for a port where port->dev is NULL.
-
-Doing that makes no sense as that causes the port detach op to get called
-for a port with nothing attached. Add an assert that port->dev != NULL when
-dev == NULL, and remove the check for not having a port->dev in the dev == NULL
-case.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb.c |    9 ++++-----
- 1 files changed, 4 insertions(+), 5 deletions(-)
-
-diff --git a/hw/usb.c b/hw/usb.c
-index 735ffd1..27a983c 100644
---- a/hw/usb.c
-+++ b/hw/usb.c
-@@ -40,12 +40,11 @@ void usb_attach(USBPort *port, USBDevice *dev)
-     } else {
-         /* detach */
-         dev = port->dev;
-+        assert(dev);
-         port->ops->detach(port);
--        if (dev) {
--            usb_send_msg(dev, USB_MSG_DETACH);
--            dev->port = NULL;
--            port->dev = NULL;
--        }
-+        usb_send_msg(dev, USB_MSG_DETACH);
-+        dev->port = NULL;
-+        port->dev = NULL;
-     }
- }
- 
--- 
-1.7.5.1
-
diff --git a/0011-usb-ehci-Fix-handling-of-PED-and-PEDC-port-status-bi.patch b/0011-usb-ehci-Fix-handling-of-PED-and-PEDC-port-status-bi.patch
deleted file mode 100644
index 6978540..0000000
--- a/0011-usb-ehci-Fix-handling-of-PED-and-PEDC-port-status-bi.patch
+++ /dev/null
@@ -1,80 +0,0 @@
-From 555ef05ebba2bf68abace047e39b12de75b71181 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Fri, 24 Jun 2011 14:36:13 +0200
-Subject: [PATCH 11/35] usb-ehci: Fix handling of PED and PEDC port status
- bits
-
-The PED bit should only be set for highspeed devices and the PEDC bit
-should not be set on "normal" PED bit changes, only on io errors.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb-ehci.c |   24 +++++++++++-------------
- 1 files changed, 11 insertions(+), 13 deletions(-)
-
-diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
-index d85e0a9..973c342 100644
---- a/hw/usb-ehci.c
-+++ b/hw/usb-ehci.c
-@@ -106,7 +106,7 @@
-  * Bits that are reserved or are read-only are masked out of values
-  * written to us by software
-  */
--#define PORTSC_RO_MASK       0x007021c4
-+#define PORTSC_RO_MASK       0x007021c0
- #define PORTSC_RWC_MASK      0x0000002a
- #define PORTSC_WKOC_E        (1 << 22)    // Wake on Over Current Enable
- #define PORTSC_WKDS_E        (1 << 21)    // Wake on Disconnect Enable
-@@ -752,7 +752,7 @@ static void ehci_detach(USBPort *port)
- 
-     ehci_queues_rip_device(s, port->dev);
- 
--    *portsc &= ~PORTSC_CONNECT;
-+    *portsc &= ~(PORTSC_CONNECT|PORTSC_PED);
-     *portsc |= PORTSC_CSC;
- 
-     /*
-@@ -847,16 +847,14 @@ static void ehci_mem_writew(void *ptr, target_phys_addr_t addr, uint32_t val)
- static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
- {
-     uint32_t *portsc = &s->portsc[port];
--    int rwc;
-     USBDevice *dev = s->ports[port].dev;
- 
--    rwc = val & PORTSC_RWC_MASK;
-+    /* Clear rwc bits */
-+    *portsc &= ~(val & PORTSC_RWC_MASK);
-+    /* The guest may clear, but not set the PED bit */
-+    *portsc &= val | ~PORTSC_PED;
-     val &= PORTSC_RO_MASK;
- 
--    // handle_read_write_clear(&val, portsc, PORTSC_PEDC | PORTSC_CSC);
--
--    *portsc &= ~rwc;
--
-     if ((val & PORTSC_PRESET) && !(*portsc & PORTSC_PRESET)) {
-         trace_usb_ehci_port_reset(port, 1);
-     }
-@@ -869,13 +867,13 @@ static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
-             *portsc &= ~PORTSC_CSC;
-         }
- 
--        /*  Table 2.16 Set the enable bit(and enable bit change) to indicate
-+        /*
-+         *  Table 2.16 Set the enable bit(and enable bit change) to indicate
-          *  to SW that this port has a high speed device attached
--         *
--         *  TODO - when to disable?
-          */
--        val |= PORTSC_PED;
--        val |= PORTSC_PEDC;
-+        if (dev && (dev->speedmask & USB_SPEED_MASK_HIGH)) {
-+            val |= PORTSC_PED;
-+        }
-     }
- 
-     *portsc &= ~PORTSC_RO_MASK;
--- 
-1.7.5.1
-
diff --git a/0011-usb-redir-Add-flow-control-support.patch b/0011-usb-redir-Add-flow-control-support.patch
new file mode 100644
index 0000000..f23ad36
--- /dev/null
+++ b/0011-usb-redir-Add-flow-control-support.patch
@@ -0,0 +1,64 @@
+From 2b797647b4a85a765bfdd8f4539d1fa10daad4fa Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 19 Jul 2011 10:56:19 +0200
+Subject: [PATCH 11/13] usb-redir: Add flow control support
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ usb-redir.c |   28 +++++++++++++++++++++++++++-
+ 1 files changed, 27 insertions(+), 1 deletions(-)
+
+diff --git a/usb-redir.c b/usb-redir.c
+index e2b5a2c..6932beb 100644
+--- a/usb-redir.c
++++ b/usb-redir.c
+@@ -224,8 +224,22 @@ static int usbredir_read(void *priv, uint8_t *data, int count)
+ static int usbredir_write(void *priv, uint8_t *data, int count)
+ {
+     USBRedirDevice *dev = priv;
++    int r;
+ 
+-    return qemu_chr_write(dev->cs, data, count);
++    if (dev->cs->write_blocked) {
++        return 0;
++    }
++
++    r = qemu_chr_write(dev->cs, data, count);
++
++    if (r < 0) {
++        if (dev->cs->write_blocked) {
++            return 0;
++        }
++        return -1;
++    }
++
++    return r;
+ }
+ 
+ /*
+@@ -782,10 +796,22 @@ static void usbredir_chardev_event(void *opaque, int event)
+     }
+ }
+ 
++static void usbredir_chardev_write_unblocked(void *opaque)
++{
++    USBRedirDevice *dev = opaque;
++
++    if (dev->parser == NULL) {
++        /* usbredir_open_close_bh hasn't handled the open event yet */
++        return;
++    }
++    usbredirparser_do_write(dev->parser);
++}
++
+ static const QemuChrHandlers usbredir_chr_handlers = {
+     .fd_can_read = usbredir_chardev_can_read,
+     .fd_read = usbredir_chardev_read,
+     .fd_event = usbredir_chardev_event,
++    .fd_write_unblocked = usbredir_chardev_write_unblocked,
+ };
+ 
+ /*
+-- 
+1.7.5.1
+
diff --git a/0012-usb-ehci-Add-support-for-registering-companion-contr.patch b/0012-usb-ehci-Add-support-for-registering-companion-contr.patch
deleted file mode 100644
index 527a1bc..0000000
--- a/0012-usb-ehci-Add-support-for-registering-companion-contr.patch
+++ /dev/null
@@ -1,321 +0,0 @@
-From 692f238a2abea35607bc8c9e76d26ae5b15518da Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Fri, 24 Jun 2011 16:18:13 +0200
-Subject: [PATCH 12/35] usb-ehci: Add support for registering companion
- controllers
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb-ehci.c |  174 +++++++++++++++++++++++++++++++++++++++++++++++----------
- 1 files changed, 144 insertions(+), 30 deletions(-)
-
-diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
-index 973c342..ec68c29 100644
---- a/hw/usb-ehci.c
-+++ b/hw/usb-ehci.c
-@@ -20,9 +20,6 @@
-  *
-  * You should have received a copy of the GNU General Public License
-  * along with this program; if not, see <http://www.gnu.org/licenses/>.
-- *
-- * TODO:
-- *  o Downstream port handoff
-  */
- 
- #include "hw.h"
-@@ -106,7 +103,7 @@
-  * Bits that are reserved or are read-only are masked out of values
-  * written to us by software
-  */
--#define PORTSC_RO_MASK       0x007021c0
-+#define PORTSC_RO_MASK       0x007001c0
- #define PORTSC_RWC_MASK      0x0000002a
- #define PORTSC_WKOC_E        (1 << 22)    // Wake on Over Current Enable
- #define PORTSC_WKDS_E        (1 << 21)    // Wake on Disconnect Enable
-@@ -373,6 +370,7 @@ struct EHCIState {
-     qemu_irq irq;
-     target_phys_addr_t mem_base;
-     int mem;
-+    int companion_count;
- 
-     /* properties */
-     uint32_t freq;
-@@ -408,6 +406,7 @@ struct EHCIState {
-     int astate;                        // Current state in asynchronous schedule
-     int pstate;                        // Current state in periodic schedule
-     USBPort ports[NB_PORTS];
-+    USBPort *companion_ports[NB_PORTS];
-     uint32_t usbsts_pending;
-     QTAILQ_HEAD(, EHCIQueue) queues;
- 
-@@ -730,17 +729,17 @@ static void ehci_attach(USBPort *port)
- 
-     trace_usb_ehci_port_attach(port->index, port->dev->product_desc);
- 
-+    if (*portsc & PORTSC_POWNER) {
-+        USBPort *companion = s->companion_ports[port->index];
-+        companion->dev = port->dev;
-+        companion->ops->attach(companion);
-+        return;
-+    }
-+
-     *portsc |= PORTSC_CONNECT;
-     *portsc |= PORTSC_CSC;
- 
--    /*
--     *  If a high speed device is attached then we own this port(indicated
--     *  by zero in the PORTSC_POWNER bit field) so set the status bit
--     *  and set an interrupt if enabled.
--     */
--    if ( !(*portsc & PORTSC_POWNER)) {
--        ehci_set_interrupt(s, USBSTS_PCD);
--    }
-+    ehci_set_interrupt(s, USBSTS_PCD);
- }
- 
- static void ehci_detach(USBPort *port)
-@@ -750,36 +749,110 @@ static void ehci_detach(USBPort *port)
- 
-     trace_usb_ehci_port_detach(port->index);
- 
-+    if (*portsc & PORTSC_POWNER) {
-+        USBPort *companion = s->companion_ports[port->index];
-+        companion->ops->detach(companion);
-+        companion->dev = NULL;
-+        return;
-+    }
-+
-     ehci_queues_rip_device(s, port->dev);
- 
-     *portsc &= ~(PORTSC_CONNECT|PORTSC_PED);
-     *portsc |= PORTSC_CSC;
- 
--    /*
--     *  If a high speed device is attached then we own this port(indicated
--     *  by zero in the PORTSC_POWNER bit field) so set the status bit
--     *  and set an interrupt if enabled.
--     */
--    if ( !(*portsc & PORTSC_POWNER)) {
--        ehci_set_interrupt(s, USBSTS_PCD);
--    }
-+    ehci_set_interrupt(s, USBSTS_PCD);
- }
- 
- static void ehci_child_detach(USBPort *port, USBDevice *child)
- {
-     EHCIState *s = port->opaque;
-+    uint32_t portsc = s->portsc[port->index];
-+
-+    if (portsc & PORTSC_POWNER) {
-+        USBPort *companion = s->companion_ports[port->index];
-+        companion->ops->child_detach(companion, child);
-+        companion->dev = NULL;
-+        return;
-+    }
- 
-     ehci_queues_rip_device(s, child);
- }
- 
-+static void ehci_wakeup(USBPort *port)
-+{
-+    EHCIState *s = port->opaque;
-+    uint32_t portsc = s->portsc[port->index];
-+
-+    if (portsc & PORTSC_POWNER) {
-+        USBPort *companion = s->companion_ports[port->index];
-+        if (companion->ops->wakeup) {
-+            companion->ops->wakeup(companion);
-+        }
-+    }
-+}
-+
-+static int ehci_register_companion(USBBus *bus, USBPort *ports[],
-+                                   uint32_t portcount, uint32_t firstport)
-+{
-+    EHCIState *s = container_of(bus, EHCIState, bus);
-+    uint32_t i;
-+
-+    if (firstport + portcount > NB_PORTS) {
-+        qerror_report(QERR_INVALID_PARAMETER_VALUE, "firstport",
-+                      "firstport on masterbus");
-+        error_printf_unless_qmp(
-+            "firstport value of %u makes companion take ports %u - %u, which "
-+            "is outside of the valid range of 0 - %u\n", firstport, firstport,
-+            firstport + portcount - 1, NB_PORTS - 1);
-+        return -1;
-+    }
-+
-+    for (i = 0; i < portcount; i++) {
-+        if (s->companion_ports[firstport + i]) {
-+            qerror_report(QERR_INVALID_PARAMETER_VALUE, "masterbus",
-+                          "an USB masterbus");
-+            error_printf_unless_qmp(
-+                "port %u on masterbus %s already has a companion assigned\n",
-+                firstport + i, bus->qbus.name);
-+            return -1;
-+        }
-+    }
-+
-+    for (i = 0; i < portcount; i++) {
-+        s->companion_ports[firstport + i] = ports[i];
-+        s->ports[firstport + i].speedmask |=
-+            USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL;
-+        /* Ensure devs attached before the initial reset go to the companion */
-+        s->portsc[firstport + i] = PORTSC_POWNER;
-+    }
-+
-+    s->companion_count++;
-+    s->mmio[0x05] = (s->companion_count << 4) | portcount;
-+
-+    return 0;
-+}
-+
- /* 4.1 host controller initialization */
- static void ehci_reset(void *opaque)
- {
-     EHCIState *s = opaque;
-     int i;
-+    USBDevice *devs[NB_PORTS];
- 
-     trace_usb_ehci_reset();
- 
-+    /*
-+     * Do the detach before touching portsc, so that it correctly gets send to
-+     * us or to our companion based on PORTSC_POWNER before the reset.
-+     */
-+    for(i = 0; i < NB_PORTS; i++) {
-+        devs[i] = s->ports[i].dev;
-+        if (devs[i]) {
-+            usb_attach(&s->ports[i], NULL);
-+        }
-+    }
-+
-     memset(&s->mmio[OPREGBASE], 0x00, MMIO_SIZE - OPREGBASE);
- 
-     s->usbcmd = NB_MAXINTRATE << USBCMD_ITC_SH;
-@@ -791,10 +864,13 @@ static void ehci_reset(void *opaque)
-     s->attach_poll_counter = 0;
- 
-     for(i = 0; i < NB_PORTS; i++) {
--        s->portsc[i] = PORTSC_POWNER | PORTSC_PPOWER;
--
--        if (s->ports[i].dev) {
--            usb_attach(&s->ports[i], s->ports[i].dev);
-+        if (s->companion_ports[i]) {
-+            s->portsc[i] = PORTSC_POWNER | PORTSC_PPOWER;
-+        } else {
-+            s->portsc[i] = PORTSC_PPOWER;
-+        }
-+        if (devs[i]) {
-+            usb_attach(&s->ports[i], devs[i]);
-         }
-     }
-     ehci_queues_rip_all(s);
-@@ -844,6 +920,34 @@ static void ehci_mem_writew(void *ptr, target_phys_addr_t addr, uint32_t val)
-     exit(1);
- }
- 
-+static void handle_port_owner_write(EHCIState *s, int port, uint32_t owner)
-+{
-+    USBDevice *dev = s->ports[port].dev;
-+    uint32_t *portsc = &s->portsc[port];
-+    uint32_t orig;
-+
-+    if (s->companion_ports[port] == NULL)
-+        return;
-+
-+    owner = owner & PORTSC_POWNER;
-+    orig  = *portsc & PORTSC_POWNER;
-+
-+    if (!(owner ^ orig)) {
-+        return;
-+    }
-+
-+    if (dev) {
-+        usb_attach(&s->ports[port], NULL);
-+    }
-+
-+    *portsc &= ~PORTSC_POWNER;
-+    *portsc |= owner;
-+
-+    if (dev) {
-+        usb_attach(&s->ports[port], dev);
-+    }
-+}
-+
- static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
- {
-     uint32_t *portsc = &s->portsc[port];
-@@ -853,6 +957,9 @@ static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
-     *portsc &= ~(val & PORTSC_RWC_MASK);
-     /* The guest may clear, but not set the PED bit */
-     *portsc &= val | ~PORTSC_PED;
-+    /* POWNER is masked out by RO_MASK as it is RO when we've no companion */
-+    handle_port_owner_write(s, port, val);
-+    /* And finally apply RO_MASK */
-     val &= PORTSC_RO_MASK;
- 
-     if ((val & PORTSC_PRESET) && !(*portsc & PORTSC_PRESET)) {
-@@ -956,7 +1063,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
-         val &= 0x1;
-         if (val) {
-             for(i = 0; i < NB_PORTS; i++)
--                s->portsc[i] &= ~PORTSC_POWNER;
-+                handle_port_owner_write(s, i, 0);
-         }
-         break;
- 
-@@ -1114,8 +1221,17 @@ static int ehci_buffer_rw(EHCIQueue *q, int bytes, int rw)
- 
- static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
- {
--    EHCIQueue *q = container_of(packet, EHCIQueue, packet);
-+    EHCIQueue *q;
-+    EHCIState *s = port->opaque;
-+    uint32_t portsc = s->portsc[port->index];
-+
-+    if (portsc & PORTSC_POWNER) {
-+        USBPort *companion = s->companion_ports[port->index];
-+        companion->ops->complete(companion, packet);
-+        return;
-+    }
- 
-+    q = container_of(packet, EHCIQueue, packet);
-     trace_usb_ehci_queue_action(q, "wakeup");
-     assert(q->async == EHCI_ASYNC_INFLIGHT);
-     q->async = EHCI_ASYNC_FINISHED;
-@@ -1245,8 +1361,6 @@ static int ehci_execute(EHCIQueue *q)
-         port = &q->ehci->ports[i];
-         dev = port->dev;
- 
--        // TODO sometime we will also need to check if we are the port owner
--
-         if (!(q->ehci->portsc[i] &(PORTSC_CONNECT))) {
-             DPRINTF("Port %d, no exec, not connected(%08X)\n",
-                     i, q->ehci->portsc[i]);
-@@ -1339,8 +1453,6 @@ static int ehci_process_itd(EHCIState *ehci,
-                 port = &ehci->ports[j];
-                 dev = port->dev;
- 
--                // TODO sometime we will also need to check if we are the port owner
--
-                 if (!(ehci->portsc[j] &(PORTSC_CONNECT))) {
-                     continue;
-                 }
-@@ -2124,10 +2236,12 @@ static USBPortOps ehci_port_ops = {
-     .attach = ehci_attach,
-     .detach = ehci_detach,
-     .child_detach = ehci_child_detach,
-+    .wakeup = ehci_wakeup,
-     .complete = ehci_async_complete_packet,
- };
- 
- static USBBusOps ehci_bus_ops = {
-+    .register_companion = ehci_register_companion,
- };
- 
- static PCIDeviceInfo ehci_info = {
--- 
-1.7.5.1
-
diff --git a/0012-usb-redir-Call-qemu_chr_guest_open-close.patch b/0012-usb-redir-Call-qemu_chr_guest_open-close.patch
new file mode 100644
index 0000000..bcf6f9c
--- /dev/null
+++ b/0012-usb-redir-Call-qemu_chr_guest_open-close.patch
@@ -0,0 +1,37 @@
+From 824ab3383370291885f1a18978018a41cfac7ee8 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Thu, 21 Jul 2011 16:28:06 +0200
+Subject: [PATCH 12/13] usb-redir: Call qemu_chr_guest_open/close
+
+To let the chardev now we're ready start receiving data. This is necessary
+with the spicevmc chardev to get it registered with the spice-server.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ usb-redir.c |    3 +++
+ 1 files changed, 3 insertions(+), 0 deletions(-)
+
+diff --git a/usb-redir.c b/usb-redir.c
+index 6932beb..d1aafda 100644
+--- a/usb-redir.c
++++ b/usb-redir.c
+@@ -840,6 +840,8 @@ static int usbredir_initfn(USBDevice *udev)
+     udev->auto_attach = 0;
+ 
+     qemu_chr_add_handlers(dev->cs, &usbredir_chr_handlers, dev);
++    /* Let the other side know we are ready */
++    qemu_chr_guest_open(dev->cs);
+ 
+     return 0;
+ }
+@@ -861,6 +863,7 @@ static void usbredir_handle_destroy(USBDevice *udev)
+ {
+     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+ 
++    qemu_chr_guest_close(dev->cs);
+     qemu_chr_close(dev->cs);
+     /* Note must be done after qemu_chr_close, as that causes a close event */
+     qemu_bh_delete(dev->open_close_bh);
+-- 
+1.7.5.1
+
diff --git a/0013-spice-qemu-char-Generate-chardev-open-close-events.patch b/0013-spice-qemu-char-Generate-chardev-open-close-events.patch
new file mode 100644
index 0000000..2ba39ad
--- /dev/null
+++ b/0013-spice-qemu-char-Generate-chardev-open-close-events.patch
@@ -0,0 +1,90 @@
+From 5149f056bd4fbeeb0ce3b850febe213a305a348b Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Thu, 21 Jul 2011 15:36:40 +0200
+Subject: [PATCH 13/13] spice-qemu-char: Generate chardev open/close events
+
+Define a state callback and make that generate chardev open/close events when
+called by the spice-server.
+
+Note that for all but the newest spice-server versions (which have a fix for
+this) the code ignores these events for a spicevmc with a subtype of vdagent,
+this subtype specific knowledge is undesirable, but unavoidable for now, see:
+http://lists.freedesktop.org/archives/spice-devel/2011-July/004837.html
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ spice-qemu-char.c |   46 +++++++++++++++++++++++++++++++++++++++++++++-
+ 1 files changed, 45 insertions(+), 1 deletions(-)
+
+diff --git a/spice-qemu-char.c b/spice-qemu-char.c
+index 2b8aec4..1f4f1ec 100644
+--- a/spice-qemu-char.c
++++ b/spice-qemu-char.c
+@@ -89,11 +89,50 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
+     return bytes;
+ }
+ 
++static void vmc_state(SpiceCharDeviceInstance *sin, int connected)
++{
++    SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
++    int event;
++
++#if SPICE_SERVER_VERSION < 0x000901
++    /*
++     * spice-server calls the state callback for the agent channel when the
++     * spice client connects / disconnects. Given that not the client but
++     * the server is doing the parsing of the messages this is wrong as the
++     * server is still listening. Worse, this causes the parser in the server
++     * to go out of sync, so we ignore state calls for subtype vdagent
++     * spicevmc chardevs. For the full story see:
++     * http://lists.freedesktop.org/archives/spice-devel/2011-July/004837.html
++     */
++    if (strcmp(sin->subtype, "vdagent") == 0) {
++        return;
++    }
++#endif
++
++    if ((scd->chr->opened && connected) ||
++        (!scd->chr->opened && !connected)) {
++        return;
++    }
++
++    if (connected) {
++        scd->chr->opened = 1;
++        event = CHR_EVENT_OPENED;
++    } else {
++        scd->chr->opened = 0;
++        event = CHR_EVENT_CLOSED;
++    }
++
++    if (scd->chr->chr_event) {
++        scd->chr->chr_event(scd->chr->handler_opaque, event);
++    }
++}
++
+ static SpiceCharDeviceInterface vmc_interface = {
+     .base.type          = SPICE_INTERFACE_CHAR_DEVICE,
+     .base.description   = "spice virtual channel char device",
+     .base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR,
+     .base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR,
++    .state              = vmc_state,
+     .write              = vmc_write,
+     .read               = vmc_read,
+ };
+@@ -222,7 +261,12 @@ int qemu_chr_open_spice(QemuOpts *opts, CharDriverState **_chr)
+     chr->chr_guest_close = spice_chr_guest_close;
+     s->unblock_timer = qemu_new_timer_ms(vm_clock, spice_chr_unblock, s);
+ 
+-    qemu_chr_generic_open(chr);
++#if SPICE_SERVER_VERSION < 0x000901
++    /* See comment in vmc_state() */
++    if (strcmp(subtype, "vdagent") == 0) {
++        qemu_chr_generic_open(chr);
++    }
++#endif
+ 
+     *_chr = chr;
+     return 0;
+-- 
+1.7.5.1
+
diff --git a/0013-usb-uhci-Add-support-for-being-a-companion-controlle.patch b/0013-usb-uhci-Add-support-for-being-a-companion-controlle.patch
deleted file mode 100644
index bb28f62..0000000
--- a/0013-usb-uhci-Add-support-for-being-a-companion-controlle.patch
+++ /dev/null
@@ -1,103 +0,0 @@
-From 850d218026df41324430af62063f68afe652a7ac Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Fri, 24 Jun 2011 17:44:53 +0200
-Subject: [PATCH 13/35] usb-uhci: Add support for being a companion controller
-
-To use as a companion controller set the masterbus property.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb-uhci.c |   41 ++++++++++++++++++++++++++++++++++++-----
- 1 files changed, 36 insertions(+), 5 deletions(-)
-
-diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
-index a46d61a..925c03b 100644
---- a/hw/usb-uhci.c
-+++ b/hw/usb-uhci.c
-@@ -132,7 +132,7 @@ typedef struct UHCIPort {
- 
- struct UHCIState {
-     PCIDevice dev;
--    USBBus bus;
-+    USBBus bus; /* Note unused when we're a companion controller */
-     uint16_t cmd; /* cmd register */
-     uint16_t status;
-     uint16_t intr; /* interrupt enable register */
-@@ -150,6 +150,10 @@ struct UHCIState {
-     /* Active packets */
-     QTAILQ_HEAD(,UHCIAsync) async_pending;
-     uint8_t num_ports_vmstate;
-+
-+    /* Properties */
-+    char *masterbus;
-+    uint32_t firstport;
- };
- 
- typedef struct UHCI_TD {
-@@ -1126,10 +1130,22 @@ static int usb_uhci_common_initfn(PCIDevice *dev)
-     pci_conf[PCI_INTERRUPT_PIN] = 4; // interrupt pin 3
-     pci_conf[USB_SBRN] = USB_RELEASE_1; // release number
- 
--    usb_bus_new(&s->bus, &uhci_bus_ops, &s->dev.qdev);
--    for(i = 0; i < NB_PORTS; i++) {
--        usb_register_port(&s->bus, &s->ports[i].port, s, i, &uhci_port_ops,
--                          USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
-+    if (s->masterbus) {
-+        USBPort *ports[NB_PORTS];
-+        for(i = 0; i < NB_PORTS; i++) {
-+            ports[i] = &s->ports[i].port;
-+        }
-+        if (usb_register_companion(s->masterbus, ports, NB_PORTS,
-+                s->firstport, s, &uhci_port_ops,
-+                USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL) != 0) {
-+            return -1;
-+        }
-+    } else {
-+        usb_bus_new(&s->bus, &uhci_bus_ops, &s->dev.qdev);
-+        for (i = 0; i < NB_PORTS; i++) {
-+            usb_register_port(&s->bus, &s->ports[i].port, s, i, &uhci_port_ops,
-+                              USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
-+        }
-     }
-     s->frame_timer = qemu_new_timer_ns(vm_clock, uhci_frame_timer, s);
-     s->num_ports_vmstate = NB_PORTS;
-@@ -1170,6 +1186,11 @@ static PCIDeviceInfo uhci_info[] = {
-         .device_id    = PCI_DEVICE_ID_INTEL_82371SB_2,
-         .revision     = 0x01,
-         .class_id     = PCI_CLASS_SERIAL_USB,
-+        .qdev.props   = (Property[]) {
-+            DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
-+            DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
-+            DEFINE_PROP_END_OF_LIST(),
-+        },
-     },{
-         .qdev.name    = "piix4-usb-uhci",
-         .qdev.size    = sizeof(UHCIState),
-@@ -1179,6 +1200,11 @@ static PCIDeviceInfo uhci_info[] = {
-         .device_id    = PCI_DEVICE_ID_INTEL_82371AB_2,
-         .revision     = 0x01,
-         .class_id     = PCI_CLASS_SERIAL_USB,
-+        .qdev.props   = (Property[]) {
-+            DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
-+            DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
-+            DEFINE_PROP_END_OF_LIST(),
-+        },
-     },{
-         .qdev.name    = "vt82c686b-usb-uhci",
-         .qdev.size    = sizeof(UHCIState),
-@@ -1188,6 +1214,11 @@ static PCIDeviceInfo uhci_info[] = {
-         .device_id    = PCI_DEVICE_ID_VIA_UHCI,
-         .revision     = 0x01,
-         .class_id     = PCI_CLASS_SERIAL_USB,
-+        .qdev.props   = (Property[]) {
-+            DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
-+            DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
-+            DEFINE_PROP_END_OF_LIST(),
-+        },
-     },{
-         /* end of list */
-     }
--- 
-1.7.5.1
-
diff --git a/0014-usb-ohci-Add-support-for-being-a-companion-controlle.patch b/0014-usb-ohci-Add-support-for-being-a-companion-controlle.patch
deleted file mode 100644
index e0688bf..0000000
--- a/0014-usb-ohci-Add-support-for-being-a-companion-controlle.patch
+++ /dev/null
@@ -1,127 +0,0 @@
-From 90ac519e89c71ac9f9731b21cef510b5cbaee38b Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Fri, 24 Jun 2011 20:29:05 +0200
-Subject: [PATCH 14/35] usb-ohci: Add support for being a companion controller
-
-To use as a companion controller, use pci-ohci as device and set the
-masterbus and num-ports properties, ie:
-
--device usb-ehci,addr=0b.1,multifunction=on,id=ehci0
--device pci-ohci,addr=0b.0,multifunction=on,masterbus=ehci0.0,num-ports=4
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb-ohci.c |   52 ++++++++++++++++++++++++++++++++++++++++------------
- 1 files changed, 40 insertions(+), 12 deletions(-)
-
-diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
-index 46f0bcb..c77a20e 100644
---- a/hw/usb-ohci.c
-+++ b/hw/usb-ohci.c
-@@ -1716,8 +1716,9 @@ static USBPortOps ohci_port_ops = {
- static USBBusOps ohci_bus_ops = {
- };
- 
--static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
--                          int num_ports, uint32_t localmem_base)
-+static int usb_ohci_init(OHCIState *ohci, DeviceState *dev,
-+                         int num_ports, uint32_t localmem_base,
-+                         char *masterbus, uint32_t firstport)
- {
-     int i;
- 
-@@ -1737,38 +1738,58 @@ static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
-                 usb_frame_time, usb_bit_time);
-     }
- 
-+    ohci->num_ports = num_ports;
-+    if (masterbus) {
-+        USBPort *ports[OHCI_MAX_PORTS];
-+        for(i = 0; i < num_ports; i++) {
-+            ports[i] = &ohci->rhport[i].port;
-+        }
-+        if (usb_register_companion(masterbus, ports, num_ports,
-+                firstport, ohci, &ohci_port_ops,
-+                USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL) != 0) {
-+            return -1;
-+        }
-+    } else {
-+        usb_bus_new(&ohci->bus, &ohci_bus_ops, dev);
-+        for (i = 0; i < num_ports; i++) {
-+            usb_register_port(&ohci->bus, &ohci->rhport[i].port,
-+                              ohci, i, &ohci_port_ops,
-+                              USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
-+        }
-+    }
-+
-     ohci->mem = cpu_register_io_memory(ohci_readfn, ohci_writefn, ohci,
-                                        DEVICE_LITTLE_ENDIAN);
-     ohci->localmem_base = localmem_base;
- 
-     ohci->name = dev->info->name;
- 
--    usb_bus_new(&ohci->bus, &ohci_bus_ops, dev);
--    ohci->num_ports = num_ports;
--    for (i = 0; i < num_ports; i++) {
--        usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, &ohci_port_ops,
--                          USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
--    }
--
-     ohci->async_td = 0;
-     qemu_register_reset(ohci_reset, ohci);
-+
-+    return 0;
- }
- 
- typedef struct {
-     PCIDevice pci_dev;
-     OHCIState state;
-+    char *masterbus;
-+    uint32_t num_ports;
-+    uint32_t firstport;
- } OHCIPCIState;
- 
- static int usb_ohci_initfn_pci(struct PCIDevice *dev)
- {
-     OHCIPCIState *ohci = DO_UPCAST(OHCIPCIState, pci_dev, dev);
--    int num_ports = 3;
- 
-     ohci->pci_dev.config[PCI_CLASS_PROG] = 0x10; /* OHCI */
-     /* TODO: RST# value should be 0. */
-     ohci->pci_dev.config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin 1 */
- 
--    usb_ohci_init(&ohci->state, &dev->qdev, num_ports, 0);
-+    if (usb_ohci_init(&ohci->state, &dev->qdev, ohci->num_ports, 0,
-+                      ohci->masterbus, ohci->firstport) != 0) {
-+        return -1;
-+    }
-     ohci->state.irq = ohci->pci_dev.irq[0];
- 
-     /* TODO: avoid cast below by using dev */
-@@ -1792,7 +1813,8 @@ static int ohci_init_pxa(SysBusDevice *dev)
- {
-     OHCISysBusState *s = FROM_SYSBUS(OHCISysBusState, dev);
- 
--    usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset);
-+    /* Cannot fail as we pass NULL for masterbus */
-+    usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset, NULL, 0);
-     sysbus_init_irq(dev, &s->ohci.irq);
-     sysbus_init_mmio(dev, 0x1000, s->ohci.mem);
- 
-@@ -1807,6 +1829,12 @@ static PCIDeviceInfo ohci_pci_info = {
-     .vendor_id    = PCI_VENDOR_ID_APPLE,
-     .device_id    = PCI_DEVICE_ID_APPLE_IPID_USB,
-     .class_id     = PCI_CLASS_SERIAL_USB,
-+    .qdev.props   = (Property[]) {
-+        DEFINE_PROP_STRING("masterbus", OHCIPCIState, masterbus),
-+        DEFINE_PROP_UINT32("num-ports", OHCIPCIState, num_ports, 3),
-+        DEFINE_PROP_UINT32("firstport", OHCIPCIState, firstport, 0),
-+        DEFINE_PROP_END_OF_LIST(),
-+    },
- };
- 
- static SysBusDeviceInfo ohci_sysbus_info = {
--- 
-1.7.5.1
-
diff --git a/0015-pci-add-ich9-usb-controller-ids.patch b/0015-pci-add-ich9-usb-controller-ids.patch
deleted file mode 100644
index 64c6f37..0000000
--- a/0015-pci-add-ich9-usb-controller-ids.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 79a91f584ad187b6f159209b3aff3d3d310e78c2 Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Fri, 1 Jul 2011 11:45:02 +0200
-Subject: [PATCH 15/35] pci: add ich9 usb controller ids
-
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/pci_ids.h |    8 ++++++++
- 1 files changed, 8 insertions(+), 0 deletions(-)
-
-diff --git a/hw/pci_ids.h b/hw/pci_ids.h
-index d94578c..927f2b0 100644
---- a/hw/pci_ids.h
-+++ b/hw/pci_ids.h
-@@ -109,5 +109,13 @@
- #define PCI_DEVICE_ID_INTEL_82371AB      0x7111
- #define PCI_DEVICE_ID_INTEL_82371AB_2    0x7112
- #define PCI_DEVICE_ID_INTEL_82371AB_3    0x7113
-+#define PCI_DEVICE_ID_INTEL_82801I_UHCI1 0x2934
-+#define PCI_DEVICE_ID_INTEL_82801I_UHCI2 0x2935
-+#define PCI_DEVICE_ID_INTEL_82801I_UHCI3 0x2936
-+#define PCI_DEVICE_ID_INTEL_82801I_UHCI4 0x2937
-+#define PCI_DEVICE_ID_INTEL_82801I_UHCI5 0x2938
-+#define PCI_DEVICE_ID_INTEL_82801I_UHCI6 0x2939
-+#define PCI_DEVICE_ID_INTEL_82801I_EHCI1 0x293a
-+#define PCI_DEVICE_ID_INTEL_82801I_EHCI2 0x293c
- 
- #define PCI_VENDOR_ID_XENSOURCE          0x5853
--- 
-1.7.5.1
-
diff --git a/0016-uhci-add-ich9-controllers.patch b/0016-uhci-add-ich9-controllers.patch
deleted file mode 100644
index c5b6897..0000000
--- a/0016-uhci-add-ich9-controllers.patch
+++ /dev/null
@@ -1,102 +0,0 @@
-From 18f499ba7cac5d66f42255f6ddf384e01bead569 Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Fri, 1 Jul 2011 09:48:49 +0200
-Subject: [PATCH 16/35] uhci: add ich9 controllers
-
-Add ich9 controllers,  Factor out properties to a separate
-struct and reference it to reduce duplication.
-
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb-uhci.c |   54 +++++++++++++++++++++++++++++++++++++++---------------
- 1 files changed, 39 insertions(+), 15 deletions(-)
-
-diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
-index 925c03b..2ef4c5b 100644
---- a/hw/usb-uhci.c
-+++ b/hw/usb-uhci.c
-@@ -1176,6 +1176,12 @@ static int usb_uhci_vt82c686b_initfn(PCIDevice *dev)
-     return usb_uhci_common_initfn(dev);
- }
- 
-+static Property uhci_properties[] = {
-+    DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
-+    DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
-+    DEFINE_PROP_END_OF_LIST(),
-+};
-+
- static PCIDeviceInfo uhci_info[] = {
-     {
-         .qdev.name    = "piix3-usb-uhci",
-@@ -1186,11 +1192,7 @@ static PCIDeviceInfo uhci_info[] = {
-         .device_id    = PCI_DEVICE_ID_INTEL_82371SB_2,
-         .revision     = 0x01,
-         .class_id     = PCI_CLASS_SERIAL_USB,
--        .qdev.props   = (Property[]) {
--            DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
--            DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
--            DEFINE_PROP_END_OF_LIST(),
--        },
-+        .qdev.props   = uhci_properties,
-     },{
-         .qdev.name    = "piix4-usb-uhci",
-         .qdev.size    = sizeof(UHCIState),
-@@ -1200,11 +1202,7 @@ static PCIDeviceInfo uhci_info[] = {
-         .device_id    = PCI_DEVICE_ID_INTEL_82371AB_2,
-         .revision     = 0x01,
-         .class_id     = PCI_CLASS_SERIAL_USB,
--        .qdev.props   = (Property[]) {
--            DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
--            DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
--            DEFINE_PROP_END_OF_LIST(),
--        },
-+        .qdev.props   = uhci_properties,
-     },{
-         .qdev.name    = "vt82c686b-usb-uhci",
-         .qdev.size    = sizeof(UHCIState),
-@@ -1214,11 +1212,37 @@ static PCIDeviceInfo uhci_info[] = {
-         .device_id    = PCI_DEVICE_ID_VIA_UHCI,
-         .revision     = 0x01,
-         .class_id     = PCI_CLASS_SERIAL_USB,
--        .qdev.props   = (Property[]) {
--            DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
--            DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
--            DEFINE_PROP_END_OF_LIST(),
--        },
-+        .qdev.props   = uhci_properties,
-+    },{
-+        .qdev.name    = "ich9-usb-uhci1",
-+        .qdev.size    = sizeof(UHCIState),
-+        .qdev.vmsd    = &vmstate_uhci,
-+        .init         = usb_uhci_common_initfn,
-+        .vendor_id    = PCI_VENDOR_ID_INTEL,
-+        .device_id    = PCI_DEVICE_ID_INTEL_82801I_UHCI1,
-+        .revision     = 0x03,
-+        .class_id     = PCI_CLASS_SERIAL_USB,
-+        .qdev.props   = uhci_properties,
-+    },{
-+        .qdev.name    = "ich9-usb-uhci2",
-+        .qdev.size    = sizeof(UHCIState),
-+        .qdev.vmsd    = &vmstate_uhci,
-+        .init         = usb_uhci_common_initfn,
-+        .vendor_id    = PCI_VENDOR_ID_INTEL,
-+        .device_id    = PCI_DEVICE_ID_INTEL_82801I_UHCI2,
-+        .revision     = 0x03,
-+        .class_id     = PCI_CLASS_SERIAL_USB,
-+        .qdev.props   = uhci_properties,
-+    },{
-+        .qdev.name    = "ich9-usb-uhci3",
-+        .qdev.size    = sizeof(UHCIState),
-+        .qdev.vmsd    = &vmstate_uhci,
-+        .init         = usb_uhci_common_initfn,
-+        .vendor_id    = PCI_VENDOR_ID_INTEL,
-+        .device_id    = PCI_DEVICE_ID_INTEL_82801I_UHCI3,
-+        .revision     = 0x03,
-+        .class_id     = PCI_CLASS_SERIAL_USB,
-+        .qdev.props   = uhci_properties,
-     },{
-         /* end of list */
-     }
--- 
-1.7.5.1
-
diff --git a/0017-ehci-fix-port-count.patch b/0017-ehci-fix-port-count.patch
deleted file mode 100644
index 13253f7..0000000
--- a/0017-ehci-fix-port-count.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From 62ffcd73894343e42b28eb1c4746ef706bd237b3 Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Fri, 1 Jul 2011 09:56:43 +0200
-Subject: [PATCH 17/35] ehci: fix port count.
-
-The ICH4 EHCI controller which we emulate has six ports not four.
-
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb-ehci.c |    2 +-
- 1 files changed, 1 insertions(+), 1 deletions(-)
-
-diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
-index ec68c29..0b959ca 100644
---- a/hw/usb-ehci.c
-+++ b/hw/usb-ehci.c
-@@ -130,7 +130,7 @@
- #define FRAME_TIMER_NS   (1000000000 / FRAME_TIMER_FREQ)
- 
- #define NB_MAXINTRATE    8        // Max rate at which controller issues ints
--#define NB_PORTS         4        // Number of downstream ports
-+#define NB_PORTS         6        // Number of downstream ports
- #define BUFF_SIZE        5*4096   // Max bytes to transfer per transaction
- #define MAX_ITERATIONS   20       // Max number of QH before we break the loop
- #define MAX_QH           100      // Max allowable queue heads in a chain
--- 
-1.7.5.1
-
diff --git a/0018-ehci-add-ich9-controller.patch b/0018-ehci-add-ich9-controller.patch
deleted file mode 100644
index dcf3a56..0000000
--- a/0018-ehci-add-ich9-controller.patch
+++ /dev/null
@@ -1,74 +0,0 @@
-From 8fe1c377cf894b7071e36e64a206f3b52ea0ab68 Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Fri, 1 Jul 2011 11:51:02 +0200
-Subject: [PATCH 18/35] ehci: add ich9 controller.
-
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb-ehci.c |   43 +++++++++++++++++++++++++++++--------------
- 1 files changed, 29 insertions(+), 14 deletions(-)
-
-diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
-index 0b959ca..a4758f9 100644
---- a/hw/usb-ehci.c
-+++ b/hw/usb-ehci.c
-@@ -2244,19 +2244,34 @@ static USBBusOps ehci_bus_ops = {
-     .register_companion = ehci_register_companion,
- };
- 
--static PCIDeviceInfo ehci_info = {
--    .qdev.name    = "usb-ehci",
--    .qdev.size    = sizeof(EHCIState),
--    .init         = usb_ehci_initfn,
--    .vendor_id    = PCI_VENDOR_ID_INTEL,
--    .device_id    = PCI_DEVICE_ID_INTEL_82801D,
--    .revision     = 0x10,
--    .class_id     = PCI_CLASS_SERIAL_USB,
--    .qdev.props   = (Property[]) {
--        DEFINE_PROP_UINT32("freq",      EHCIState, freq, FRAME_TIMER_FREQ),
--        DEFINE_PROP_UINT32("maxframes", EHCIState, maxframes, 128),
--        DEFINE_PROP_END_OF_LIST(),
--    },
-+static Property ehci_properties[] = {
-+    DEFINE_PROP_UINT32("freq",      EHCIState, freq, FRAME_TIMER_FREQ),
-+    DEFINE_PROP_UINT32("maxframes", EHCIState, maxframes, 128),
-+    DEFINE_PROP_END_OF_LIST(),
-+};
-+
-+static PCIDeviceInfo ehci_info[] = {
-+    {
-+        .qdev.name    = "usb-ehci",
-+        .qdev.size    = sizeof(EHCIState),
-+        .init         = usb_ehci_initfn,
-+        .vendor_id    = PCI_VENDOR_ID_INTEL,
-+        .device_id    = PCI_DEVICE_ID_INTEL_82801D, /* ich4 */
-+        .revision     = 0x10,
-+        .class_id     = PCI_CLASS_SERIAL_USB,
-+        .qdev.props   = ehci_properties,
-+    },{
-+        .qdev.name    = "ich9-usb-ehci1",
-+        .qdev.size    = sizeof(EHCIState),
-+        .init         = usb_ehci_initfn,
-+        .vendor_id    = PCI_VENDOR_ID_INTEL,
-+        .device_id    = PCI_DEVICE_ID_INTEL_82801I_EHCI1,
-+        .revision     = 0x03,
-+        .class_id     = PCI_CLASS_SERIAL_USB,
-+        .qdev.props   = ehci_properties,
-+    },{
-+        /* end of list */
-+    }
- };
- 
- static int usb_ehci_initfn(PCIDevice *dev)
-@@ -2335,7 +2350,7 @@ static int usb_ehci_initfn(PCIDevice *dev)
- 
- static void ehci_register(void)
- {
--    pci_qdev_register(&ehci_info);
-+    pci_qdev_register_many(ehci_info);
- }
- device_init(ehci_register);
- 
--- 
-1.7.5.1
-
diff --git a/0019-usb-update-documentation.patch b/0019-usb-update-documentation.patch
deleted file mode 100644
index af65a25..0000000
--- a/0019-usb-update-documentation.patch
+++ /dev/null
@@ -1,112 +0,0 @@
-From 097e10ae52ea3c4fd2ac9b019a1de9a4649e8f2e Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Tue, 5 Jul 2011 16:58:41 +0200
-Subject: [PATCH 19/35] usb: update documentation
-
-Add a paragraph on companion controller mode and a
-configuration file which sets it all up for you.
-
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- docs/ich9-ehci-uhci.cfg |   37 +++++++++++++++++++++++++++++++++++++
- docs/usb2.txt           |   33 ++++++++++++++++++++++++++++-----
- 2 files changed, 65 insertions(+), 5 deletions(-)
- create mode 100644 docs/ich9-ehci-uhci.cfg
-
-diff --git a/docs/ich9-ehci-uhci.cfg b/docs/ich9-ehci-uhci.cfg
-new file mode 100644
-index 0000000..a0e9b96
---- /dev/null
-+++ b/docs/ich9-ehci-uhci.cfg
-@@ -0,0 +1,37 @@
-+###########################################################################
-+#
-+# You can pass this file directly to qemu using the -readconfig
-+# command line switch.
-+#
-+# This config file creates a EHCI adapter with companion UHCI
-+# controllers as multifunction device in PCI slot "1d".
-+#
-+# Specify "bus=ehci.0" when creating usb devices to hook them up
-+# there.
-+#
-+
-+[device "ehci"]
-+  driver = "ich9-usb-ehci1"
-+  addr = "1d.7"
-+  multifunction = "on"
-+
-+[device "uhci-1"]
-+  driver = "ich9-usb-uhci1"
-+  addr = "1d.0"
-+  multifunction = "on"
-+  masterbus = "ehci.0"
-+  firstport = "0"
-+
-+[device "uhci-2"]
-+  driver = "ich9-usb-uhci2"
-+  addr = "1d.1"
-+  multifunction = "on"
-+  masterbus = "ehci.0"
-+  firstport = "2"
-+
-+[device "uhci-3"]
-+  driver = "ich9-usb-uhci3"
-+  addr = "1d.2"
-+  multifunction = "on"
-+  masterbus = "ehci.0"
-+  firstport = "4"
-diff --git a/docs/usb2.txt b/docs/usb2.txt
-index 5950c71..228aa33 100644
---- a/docs/usb2.txt
-+++ b/docs/usb2.txt
-@@ -2,11 +2,13 @@
- USB 2.0 Quick Start
- ===================
- 
--The QEMU EHCI Adapter does *not* support companion controllers.  That
--implies there are two completely separate USB busses: One USB 1.1 bus
--driven by the UHCI controller and one USB 2.0 bus driven by the EHCI
--controller.  Devices must be attached to the correct controller
--manually.
-+The QEMU EHCI Adapter can be used with and without companion
-+controllers.  See below for the companion controller mode.
-+
-+When not running in companion controller mode there are two completely
-+separate USB busses: One USB 1.1 bus driven by the UHCI controller and
-+one USB 2.0 bus driven by the EHCI controller.  Devices must be
-+attached to the correct controller manually.
- 
- The '-usb' switch will make qemu create the UHCI controller as part of
- the PIIX3 chipset.  The USB 1.1 bus will carry the name "usb.0".
-@@ -32,6 +34,27 @@ This attaches a usb tablet to the UHCI adapter and a usb mass storage
- device to the EHCI adapter.
- 
- 
-+Companion controller support
-+----------------------------
-+
-+Companion controller support has been added recently.  The operational
-+model described above with two completely separate busses still works
-+fine.  Additionally the UHCI and OHCI controllers got the ability to
-+attach to a usb bus created by EHCI as companion controllers.  This is
-+done by specifying the masterbus and firstport properties.  masterbus
-+specifies the bus name the controller should attach to.  firstport
-+specifies the first port the controller should attach to, which is
-+needed as usually one ehci controller with six ports has three uhci
-+companion controllers with two ports each.
-+
-+There is a config file in docs which will do all this for you, just
-+try ...
-+
-+    qemu -readconfig docs/ich9-ehci-uhci.cfg
-+
-+... then use "bus=ehci.0" to assign your usb devices to that bus.
-+
-+
- More USB tips & tricks
- ======================
- 
--- 
-1.7.5.1
-
diff --git a/0020-usb_register_port-do-not-set-port-opaque-and-port-in.patch b/0020-usb_register_port-do-not-set-port-opaque-and-port-in.patch
deleted file mode 100644
index ff3d32e..0000000
--- a/0020-usb_register_port-do-not-set-port-opaque-and-port-in.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From 88a8f55b17e9e6c78ce620ac91012bfd822f8f04 Mon Sep 17 00:00:00 2001
-From: Jes Sorensen <Jes.Sorensen@redhat.com>
-Date: Mon, 4 Jul 2011 17:33:05 +0200
-Subject: [PATCH 20/35] usb_register_port(): do not set port->opaque and
- port->index twice
-
-Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb-bus.c |    2 --
- 1 files changed, 0 insertions(+), 2 deletions(-)
-
-diff --git a/hw/usb-bus.c b/hw/usb-bus.c
-index c8347e9..f1dd55e 100644
---- a/hw/usb-bus.c
-+++ b/hw/usb-bus.c
-@@ -143,8 +143,6 @@ static void usb_fill_port(USBPort *port, void *opaque, int index,
- {
-     port->opaque = opaque;
-     port->index = index;
--    port->opaque = opaque;
--    port->index = index;
-     port->ops = ops;
-     port->speedmask = speedmask;
-     usb_port_location(port, NULL, index + 1);
--- 
-1.7.5.1
-
diff --git a/0021-usb-fixup-bluetooth-descriptors.patch b/0021-usb-fixup-bluetooth-descriptors.patch
deleted file mode 100644
index d81d1b2..0000000
--- a/0021-usb-fixup-bluetooth-descriptors.patch
+++ /dev/null
@@ -1,116 +0,0 @@
-From 1d729b8511fd72f66d7cc10e801a546daa40bb79 Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Wed, 6 Jul 2011 12:40:28 +0200
-Subject: [PATCH 21/35] usb: fixup bluetooth descriptors
-
-Commit 4696425cd05c7baa0a4b469d43ba4b8488bcfc0f changes some
-endpoints from isocrounous to interrupt by mistake.  Fix it.
-
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb-bt.c |   24 ++++++++++++------------
- 1 files changed, 12 insertions(+), 12 deletions(-)
-
-diff --git a/hw/usb-bt.c b/hw/usb-bt.c
-index baae487..e364513 100644
---- a/hw/usb-bt.c
-+++ b/hw/usb-bt.c
-@@ -99,13 +99,13 @@ static const USBDescIface desc_iface_bluetooth[] = {
-         .eps = (USBDescEndpoint[]) {
-             {
-                 .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
--                .bmAttributes          = USB_ENDPOINT_XFER_INT,
-+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                 .wMaxPacketSize        = 0,
-                 .bInterval             = 0x01,
-             },
-             {
-                 .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
--                .bmAttributes          = USB_ENDPOINT_XFER_INT,
-+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                 .wMaxPacketSize        = 0,
-                 .bInterval             = 0x01,
-             },
-@@ -120,13 +120,13 @@ static const USBDescIface desc_iface_bluetooth[] = {
-         .eps = (USBDescEndpoint[]) {
-             {
-                 .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
--                .bmAttributes          = USB_ENDPOINT_XFER_INT,
-+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                 .wMaxPacketSize        = 0x09,
-                 .bInterval             = 0x01,
-             },
-             {
-                 .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
--                .bmAttributes          = USB_ENDPOINT_XFER_INT,
-+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                 .wMaxPacketSize        = 0x09,
-                 .bInterval             = 0x01,
-             },
-@@ -141,13 +141,13 @@ static const USBDescIface desc_iface_bluetooth[] = {
-         .eps = (USBDescEndpoint[]) {
-             {
-                 .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
--                .bmAttributes          = USB_ENDPOINT_XFER_INT,
-+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                 .wMaxPacketSize        = 0x11,
-                 .bInterval             = 0x01,
-             },
-             {
-                 .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
--                .bmAttributes          = USB_ENDPOINT_XFER_INT,
-+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                 .wMaxPacketSize        = 0x11,
-                 .bInterval             = 0x01,
-             },
-@@ -162,13 +162,13 @@ static const USBDescIface desc_iface_bluetooth[] = {
-         .eps = (USBDescEndpoint[]) {
-             {
-                 .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
--                .bmAttributes          = USB_ENDPOINT_XFER_INT,
-+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                 .wMaxPacketSize        = 0x19,
-                 .bInterval             = 0x01,
-             },
-             {
-                 .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
--                .bmAttributes          = USB_ENDPOINT_XFER_INT,
-+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                 .wMaxPacketSize        = 0x19,
-                 .bInterval             = 0x01,
-             },
-@@ -183,13 +183,13 @@ static const USBDescIface desc_iface_bluetooth[] = {
-         .eps = (USBDescEndpoint[]) {
-             {
-                 .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
--                .bmAttributes          = USB_ENDPOINT_XFER_INT,
-+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                 .wMaxPacketSize        = 0x21,
-                 .bInterval             = 0x01,
-             },
-             {
-                 .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
--                .bmAttributes          = USB_ENDPOINT_XFER_INT,
-+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                 .wMaxPacketSize        = 0x21,
-                 .bInterval             = 0x01,
-             },
-@@ -204,13 +204,13 @@ static const USBDescIface desc_iface_bluetooth[] = {
-         .eps = (USBDescEndpoint[]) {
-             {
-                 .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
--                .bmAttributes          = USB_ENDPOINT_XFER_INT,
-+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                 .wMaxPacketSize        = 0x31,
-                 .bInterval             = 0x01,
-             },
-             {
-                 .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
--                .bmAttributes          = USB_ENDPOINT_XFER_INT,
-+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                 .wMaxPacketSize        = 0x31,
-                 .bInterval             = 0x01,
-             },
--- 
-1.7.5.1
-
diff --git a/0022-usb-hub-remove-unused-descriptor-arrays.patch b/0022-usb-hub-remove-unused-descriptor-arrays.patch
deleted file mode 100644
index 3f5aa9a..0000000
--- a/0022-usb-hub-remove-unused-descriptor-arrays.patch
+++ /dev/null
@@ -1,95 +0,0 @@
-From d9c7f506bea5ed587ecf2178276e4bf82e370a67 Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Thu, 7 Jul 2011 15:02:58 +0200
-Subject: [PATCH 22/35] usb-hub: remove unused descriptor arrays
-
-Somehow they where left over when converting the hub
-to the new usb descriptor infrastructure ...
-
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb-hub.c |   68 ----------------------------------------------------------
- 1 files changed, 0 insertions(+), 68 deletions(-)
-
-diff --git a/hw/usb-hub.c b/hw/usb-hub.c
-index b7557ce..b49a2fe 100644
---- a/hw/usb-hub.c
-+++ b/hw/usb-hub.c
-@@ -138,74 +138,6 @@ static const USBDesc desc_hub = {
-     .str  = desc_strings,
- };
- 
--static const uint8_t qemu_hub_dev_descriptor[] = {
--	0x12,       /*  u8 bLength; */
--	0x01,       /*  u8 bDescriptorType; Device */
--	0x10, 0x01, /*  u16 bcdUSB; v1.1 */
--
--	0x09,	    /*  u8  bDeviceClass; HUB_CLASSCODE */
--	0x00,	    /*  u8  bDeviceSubClass; */
--	0x00,       /*  u8  bDeviceProtocol; [ low/full speeds only ] */
--	0x08,       /*  u8  bMaxPacketSize0; 8 Bytes */
--
--	0x00, 0x00, /*  u16 idVendor; */
-- 	0x00, 0x00, /*  u16 idProduct; */
--	0x01, 0x01, /*  u16 bcdDevice */
--
--	0x03,       /*  u8  iManufacturer; */
--	0x02,       /*  u8  iProduct; */
--	0x01,       /*  u8  iSerialNumber; */
--	0x01        /*  u8  bNumConfigurations; */
--};
--
--/* XXX: patch interrupt size */
--static const uint8_t qemu_hub_config_descriptor[] = {
--
--	/* one configuration */
--	0x09,       /*  u8  bLength; */
--	0x02,       /*  u8  bDescriptorType; Configuration */
--	0x19, 0x00, /*  u16 wTotalLength; */
--	0x01,       /*  u8  bNumInterfaces; (1) */
--	0x01,       /*  u8  bConfigurationValue; */
--	0x00,       /*  u8  iConfiguration; */
--	0xe0,       /*  u8  bmAttributes;
--				 Bit 7: must be set,
--				     6: Self-powered,
--				     5: Remote wakeup,
--				     4..0: resvd */
--	0x00,       /*  u8  MaxPower; */
--
--	/* USB 1.1:
--	 * USB 2.0, single TT organization (mandatory):
--	 *	one interface, protocol 0
--	 *
--	 * USB 2.0, multiple TT organization (optional):
--	 *	two interfaces, protocols 1 (like single TT)
--	 *	and 2 (multiple TT mode) ... config is
--	 *	sometimes settable
--	 *	NOT IMPLEMENTED
--	 */
--
--	/* one interface */
--	0x09,       /*  u8  if_bLength; */
--	0x04,       /*  u8  if_bDescriptorType; Interface */
--	0x00,       /*  u8  if_bInterfaceNumber; */
--	0x00,       /*  u8  if_bAlternateSetting; */
--	0x01,       /*  u8  if_bNumEndpoints; */
--	0x09,       /*  u8  if_bInterfaceClass; HUB_CLASSCODE */
--	0x00,       /*  u8  if_bInterfaceSubClass; */
--	0x00,       /*  u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
--	0x00,       /*  u8  if_iInterface; */
--
--	/* one endpoint (status change endpoint) */
--	0x07,       /*  u8  ep_bLength; */
--	0x05,       /*  u8  ep_bDescriptorType; Endpoint */
--	0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
-- 	0x03,       /*  u8  ep_bmAttributes; Interrupt */
-- 	0x02, 0x00, /*  u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
--	0xff        /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
--};
--
- static const uint8_t qemu_hub_hub_descriptor[] =
- {
- 	0x00,			/*  u8  bLength; patched in later */
--- 
-1.7.5.1
-
diff --git a/0023-usb-ohci-raise-interrupt-on-attach.patch b/0023-usb-ohci-raise-interrupt-on-attach.patch
deleted file mode 100644
index 63dd15d..0000000
--- a/0023-usb-ohci-raise-interrupt-on-attach.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From a0559e6445bf2cceba279bf3bcdc062497872db1 Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Thu, 7 Jul 2011 15:18:50 +0200
-Subject: [PATCH 23/35] usb-ohci: raise interrupt on attach
-
-Got lost in commit 618c169b577db64ac6589ad48825d2e11760d1a6,
-add it back in.  Also fix codestyle while we are at it.
-
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb-ohci.c |    8 +++++++-
- 1 files changed, 7 insertions(+), 1 deletions(-)
-
-diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
-index c77a20e..8491d59 100644
---- a/hw/usb-ohci.c
-+++ b/hw/usb-ohci.c
-@@ -327,6 +327,7 @@ static void ohci_attach(USBPort *port1)
- {
-     OHCIState *s = port1->opaque;
-     OHCIPort *port = &s->rhport[port1->index];
-+    uint32_t old_state = port->ctrl;
- 
-     /* set connect status */
-     port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
-@@ -344,6 +345,10 @@ static void ohci_attach(USBPort *port1)
-     }
- 
-     DPRINTF("usb-ohci: Attached port %d\n", port1->index);
-+
-+    if (old_state != port->ctrl) {
-+        ohci_set_interrupt(s, OHCI_INTR_RHSC);
-+    }
- }
- 
- static void ohci_detach(USBPort *port1)
-@@ -366,8 +371,9 @@ static void ohci_detach(USBPort *port1)
-     }
-     DPRINTF("usb-ohci: Detached port %d\n", port1->index);
- 
--    if (old_state != port->ctrl)
-+    if (old_state != port->ctrl) {
-         ohci_set_interrupt(s, OHCI_INTR_RHSC);
-+    }
- }
- 
- static void ohci_wakeup(USBPort *port1)
--- 
-1.7.5.1
-
diff --git a/0024-USB-add-usb-network-redirection-support.patch b/0024-USB-add-usb-network-redirection-support.patch
deleted file mode 100644
index 88ebda4..0000000
--- a/0024-USB-add-usb-network-redirection-support.patch
+++ /dev/null
@@ -1,1346 +0,0 @@
-From 961391dad70649ac54a3011b5f9ba54f44d476e6 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Tue, 31 May 2011 14:59:41 +0200
-Subject: [PATCH 24/35] USB: add usb network redirection support
-
-This patch adds support for a usb-redir device, which takes a chardev
-as a communication channel to an actual usbdevice using the usbredir protocol.
-
-Compiling the usb-redir device requires usbredir-0.3 to be installed for
-the usbredir protocol parser, usbredir-0.3 also contains a server for
-redirecting usb traffic from an actual usb device. You can get the 0.3
-release of usbredir here:
-http://people.fedoraproject.org/~jwrdegoede/usbredir-0.3.tar.bz2
-(getting a more formal site for it is a WIP)
-
-Example usage:
-1) Start usbredirserver for a usb device:
-sudo usbredirserver 045e:0772
-2) Start qemu with usb2 support + a chardev talking to usbredirserver +
-   a usb-redir device using this chardev:
-qemu ... \
-  -readconfig docs/ich9-ehci-uhci.cfg \
-  -chardev socket,id=usbredirchardev,host=localhost,port=4000 \
-  -device usb-redir,chardev=usbredirchardev,id=usbredirdev
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- Makefile.objs |    1 +
- configure     |   28 ++
- usb-redir.c   | 1218 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 1247 insertions(+), 0 deletions(-)
- create mode 100644 usb-redir.c
-
-diff --git a/Makefile.objs b/Makefile.objs
-index dbde6b1..ed8cfa2 100644
---- a/Makefile.objs
-+++ b/Makefile.objs
-@@ -208,6 +208,7 @@ hw-obj-$(CONFIG_HPET) += hpet.o
- hw-obj-$(CONFIG_APPLESMC) += applesmc.o
- hw-obj-$(CONFIG_SMARTCARD) += usb-ccid.o ccid-card-passthru.o
- hw-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
-+hw-obj-$(CONFIG_USB_REDIR) += usb-redir.o
- 
- # PPC devices
- hw-obj-$(CONFIG_OPENPIC) += openpic.o
-diff --git a/configure b/configure
-index a896f11..4576f21 100755
---- a/configure
-+++ b/configure
-@@ -190,6 +190,7 @@ spice=""
- rbd=""
- smartcard=""
- smartcard_nss=""
-+usb_redir=""
- opengl=""
- 
- # parse CC options first
-@@ -773,6 +774,10 @@ for opt do
-   ;;
-   --enable-smartcard-nss) smartcard_nss="yes"
-   ;;
-+  --disable-usb-redir) usb_redir="no"
-+  ;;
-+  --enable-usb-redir) usb_redir="yes"
-+  ;;
-   *) echo "ERROR: unknown option $opt"; show_help="yes"
-   ;;
-   esac
-@@ -1053,6 +1058,8 @@ echo "  --disable-smartcard      disable smartcard support"
- echo "  --enable-smartcard       enable smartcard support"
- echo "  --disable-smartcard-nss  disable smartcard nss support"
- echo "  --enable-smartcard-nss   enable smartcard nss support"
-+echo "  --disable-usb-redir      disable usb network redirection support"
-+echo "  --enable-usb-redir       enable usb network redirection support"
- echo ""
- echo "NOTE: The object files are built at the place where configure is launched"
- exit 1
-@@ -2427,6 +2434,22 @@ if test "$smartcard" = "no" ; then
-     smartcard_nss="no"
- fi
- 
-+# check for usbredirparser for usb network redirection support
-+if test "$usb_redir" != "no" ; then
-+    if $pkg_config libusbredirparser >/dev/null 2>&1 ; then
-+        usb_redir="yes"
-+        usb_redir_cflags=$($pkg_config --cflags libusbredirparser 2>/dev/null)
-+        usb_redir_libs=$($pkg_config --libs libusbredirparser 2>/dev/null)
-+        QEMU_CFLAGS="$QEMU_CFLAGS $usb_redir_cflags"
-+        LIBS="$LIBS $usb_redir_libs"
-+    else
-+        if test "$usb_redir" = "yes"; then
-+            feature_not_found "usb-redir"
-+        fi
-+        usb_redir="no"
-+    fi
-+fi
-+
- ##########################################
- 
- ##########################################
-@@ -2676,6 +2699,7 @@ echo "spice support     $spice"
- echo "rbd support       $rbd"
- echo "xfsctl support    $xfs"
- echo "nss used          $smartcard_nss"
-+echo "usb net redir     $usb_redir"
- echo "OpenGL support    $opengl"
- 
- if test $sdl_too_old = "yes"; then
-@@ -2974,6 +2998,10 @@ if test "$smartcard_nss" = "yes" ; then
-   echo "CONFIG_SMARTCARD_NSS=y" >> $config_host_mak
- fi
- 
-+if test "$usb_redir" = "yes" ; then
-+  echo "CONFIG_USB_REDIR=y" >> $config_host_mak
-+fi
-+
- if test "$opengl" = "yes" ; then
-   echo "CONFIG_OPENGL=y" >> $config_host_mak
- fi
-diff --git a/usb-redir.c b/usb-redir.c
-new file mode 100644
-index 0000000..e212993
---- /dev/null
-+++ b/usb-redir.c
-@@ -0,0 +1,1218 @@
-+/*
-+ * USB redirector usb-guest
-+ *
-+ * Copyright (c) 2011 Red Hat, Inc.
-+ *
-+ * Red Hat Authors:
-+ * Hans de Goede <hdegoede@redhat.com>
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a copy
-+ * of this software and associated documentation files (the "Software"), to deal
-+ * in the Software without restriction, including without limitation the rights
-+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-+ * copies of the Software, and to permit persons to whom the Software is
-+ * furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-+ * THE SOFTWARE.
-+ */
-+
-+#include "qemu-common.h"
-+#include "qemu-timer.h"
-+#include "monitor.h"
-+#include "sysemu.h"
-+
-+#include <dirent.h>
-+#include <sys/ioctl.h>
-+#include <signal.h>
-+#include <usbredirparser.h>
-+
-+#include "hw/usb.h"
-+
-+#define MAX_ENDPOINTS 32
-+#define EP2I(ep_address) (((ep_address & 0x80) >> 3) | (ep_address & 0x0f))
-+#define I2EP(i) (((i & 0x10) << 3) | (i & 0x0f))
-+
-+typedef struct AsyncURB AsyncURB;
-+typedef struct USBRedirDevice USBRedirDevice;
-+
-+/* Struct to hold buffered packets (iso or int input packets) */
-+struct buf_packet {
-+    uint8_t *data;
-+    int len;
-+    int status;
-+    QTAILQ_ENTRY(buf_packet)next;
-+};
-+
-+struct endp_data {
-+    uint8_t type;
-+    uint8_t interval;
-+    uint8_t interface; /* bInterfaceNumber this ep belongs to */
-+    uint8_t iso_started;
-+    uint8_t iso_error; /* For reporting iso errors to the HC */
-+    uint8_t interrupt_started;
-+    uint8_t interrupt_error;
-+    QTAILQ_HEAD(, buf_packet) bufpq;
-+};
-+
-+struct USBRedirDevice {
-+    USBDevice dev;
-+    /* Properties */
-+    CharDriverState *cs;
-+    uint8_t debug;
-+    /* Data passed from chardev the fd_read cb to the usbredirparser read cb */
-+    const uint8_t *read_buf;
-+    int read_buf_size;
-+    /* For async handling of open/close */
-+    QEMUBH *open_close_bh;
-+    /* To delay the usb attach in case of quick chardev close + open */
-+    QEMUTimer *attach_timer;
-+    int64_t next_attach_time;
-+    struct usbredirparser *parser;
-+    struct endp_data endpoint[MAX_ENDPOINTS];
-+    uint32_t packet_id;
-+    QTAILQ_HEAD(, AsyncURB) asyncq;
-+};
-+
-+struct AsyncURB {
-+    USBRedirDevice *dev;
-+    USBPacket *packet;
-+    uint32_t packet_id;
-+    int get;
-+    union {
-+        struct usb_redir_control_packet_header control_packet;
-+        struct usb_redir_bulk_packet_header bulk_packet;
-+        struct usb_redir_interrupt_packet_header interrupt_packet;
-+    };
-+    QTAILQ_ENTRY(AsyncURB)next;
-+};
-+
-+static void usbredir_device_connect(void *priv,
-+    struct usb_redir_device_connect_header *device_connect);
-+static void usbredir_device_disconnect(void *priv);
-+static void usbredir_interface_info(void *priv,
-+    struct usb_redir_interface_info_header *interface_info);
-+static void usbredir_ep_info(void *priv,
-+    struct usb_redir_ep_info_header *ep_info);
-+static void usbredir_configuration_status(void *priv, uint32_t id,
-+    struct usb_redir_configuration_status_header *configuration_status);
-+static void usbredir_alt_setting_status(void *priv, uint32_t id,
-+    struct usb_redir_alt_setting_status_header *alt_setting_status);
-+static void usbredir_iso_stream_status(void *priv, uint32_t id,
-+    struct usb_redir_iso_stream_status_header *iso_stream_status);
-+static void usbredir_interrupt_receiving_status(void *priv, uint32_t id,
-+    struct usb_redir_interrupt_receiving_status_header
-+    *interrupt_receiving_status);
-+static void usbredir_bulk_streams_status(void *priv, uint32_t id,
-+    struct usb_redir_bulk_streams_status_header *bulk_streams_status);
-+static void usbredir_control_packet(void *priv, uint32_t id,
-+    struct usb_redir_control_packet_header *control_packet,
-+    uint8_t *data, int data_len);
-+static void usbredir_bulk_packet(void *priv, uint32_t id,
-+    struct usb_redir_bulk_packet_header *bulk_packet,
-+    uint8_t *data, int data_len);
-+static void usbredir_iso_packet(void *priv, uint32_t id,
-+    struct usb_redir_iso_packet_header *iso_packet,
-+    uint8_t *data, int data_len);
-+static void usbredir_interrupt_packet(void *priv, uint32_t id,
-+    struct usb_redir_interrupt_packet_header *interrupt_header,
-+    uint8_t *data, int data_len);
-+
-+static int usbredir_handle_status(USBRedirDevice *dev,
-+                                       int status, int actual_len);
-+
-+#define VERSION "qemu usb-redir guest " QEMU_VERSION
-+
-+/*
-+ * Logging stuff
-+ */
-+
-+#define ERROR(...) \
-+    do { \
-+        if (dev->debug >= usbredirparser_error) { \
-+            error_report("usb-redir error: " __VA_ARGS__); \
-+        } \
-+    } while (0)
-+#define WARNING(...) \
-+    do { \
-+        if (dev->debug >= usbredirparser_warning) { \
-+            error_report("usb-redir warning: " __VA_ARGS__); \
-+        } \
-+    } while (0)
-+#define INFO(...) \
-+    do { \
-+        if (dev->debug >= usbredirparser_info) { \
-+            error_report("usb-redir: " __VA_ARGS__); \
-+        } \
-+    } while (0)
-+#define DPRINTF(...) \
-+    do { \
-+        if (dev->debug >= usbredirparser_debug) { \
-+            error_report("usb-redir: " __VA_ARGS__); \
-+        } \
-+    } while (0)
-+#define DPRINTF2(...) \
-+    do { \
-+        if (dev->debug >= usbredirparser_debug_data) { \
-+            error_report("usb-redir: " __VA_ARGS__); \
-+        } \
-+    } while (0)
-+
-+static void usbredir_log(void *priv, int level, const char *msg)
-+{
-+    USBRedirDevice *dev = priv;
-+
-+    if (dev->debug < level) {
-+        return;
-+    }
-+
-+    error_report("%s\n", msg);
-+}
-+
-+static void usbredir_log_data(USBRedirDevice *dev, const char *desc,
-+    const uint8_t *data, int len)
-+{
-+    int i, j, n;
-+
-+    if (dev->debug < usbredirparser_debug_data) {
-+        return;
-+    }
-+
-+    for (i = 0; i < len; i += j) {
-+        char buf[128];
-+
-+        n = sprintf(buf, "%s", desc);
-+        for (j = 0; j < 8 && i + j < len; j++) {
-+            n += sprintf(buf + n, " %02X", data[i + j]);
-+        }
-+        error_report("%s\n", buf);
-+    }
-+}
-+
-+/*
-+ * usbredirparser io functions
-+ */
-+
-+static int usbredir_read(void *priv, uint8_t *data, int count)
-+{
-+    USBRedirDevice *dev = priv;
-+
-+    if (dev->read_buf_size < count) {
-+        count = dev->read_buf_size;
-+    }
-+
-+    memcpy(data, dev->read_buf, count);
-+
-+    dev->read_buf_size -= count;
-+    if (dev->read_buf_size) {
-+        dev->read_buf += count;
-+    } else {
-+        dev->read_buf = NULL;
-+    }
-+
-+    return count;
-+}
-+
-+static int usbredir_write(void *priv, uint8_t *data, int count)
-+{
-+    USBRedirDevice *dev = priv;
-+
-+    return qemu_chr_write(dev->cs, data, count);
-+}
-+
-+/*
-+ * Async and buffered packets helpers
-+ */
-+
-+static AsyncURB *async_alloc(USBRedirDevice *dev, USBPacket *p)
-+{
-+    AsyncURB *aurb = (AsyncURB *) qemu_mallocz(sizeof(AsyncURB));
-+    aurb->dev = dev;
-+    aurb->packet = p;
-+    aurb->packet_id = dev->packet_id;
-+    QTAILQ_INSERT_TAIL(&dev->asyncq, aurb, next);
-+    dev->packet_id++;
-+
-+    return aurb;
-+}
-+
-+static void async_free(USBRedirDevice *dev, AsyncURB *aurb)
-+{
-+    QTAILQ_REMOVE(&dev->asyncq, aurb, next);
-+    qemu_free(aurb);
-+}
-+
-+static AsyncURB *async_find(USBRedirDevice *dev, uint32_t packet_id)
-+{
-+    AsyncURB *aurb;
-+
-+    QTAILQ_FOREACH(aurb, &dev->asyncq, next) {
-+        if (aurb->packet_id == packet_id) {
-+            return aurb;
-+        }
-+    }
-+    ERROR("could not find async urb for packet_id %u\n", packet_id);
-+    return NULL;
-+}
-+
-+static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p)
-+{
-+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
-+    AsyncURB *aurb;
-+
-+    QTAILQ_FOREACH(aurb, &dev->asyncq, next) {
-+        if (p != aurb->packet) {
-+            continue;
-+        }
-+
-+        DPRINTF("async cancel id %u\n", aurb->packet_id);
-+        usbredirparser_send_cancel_data_packet(dev->parser, aurb->packet_id);
-+        usbredirparser_do_write(dev->parser);
-+
-+        /* Mark it as dead */
-+        aurb->packet = NULL;
-+        break;
-+    }
-+}
-+
-+static struct buf_packet *bufp_alloc(USBRedirDevice *dev,
-+    uint8_t *data, int len, int status, uint8_t ep)
-+{
-+    struct buf_packet *bufp = qemu_malloc(sizeof(struct buf_packet));
-+    bufp->data   = data;
-+    bufp->len    = len;
-+    bufp->status = status;
-+    QTAILQ_INSERT_TAIL(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
-+    return bufp;
-+}
-+
-+static void bufp_free(USBRedirDevice *dev, struct buf_packet *bufp,
-+    uint8_t ep)
-+{
-+    QTAILQ_REMOVE(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
-+    free(bufp->data);
-+    qemu_free(bufp);
-+}
-+
-+static void usbredir_free_bufpq(USBRedirDevice *dev, uint8_t ep)
-+{
-+    struct buf_packet *buf, *buf_next;
-+
-+    QTAILQ_FOREACH_SAFE(buf, &dev->endpoint[EP2I(ep)].bufpq, next, buf_next) {
-+        bufp_free(dev, buf, ep);
-+    }
-+}
-+
-+/*
-+ * USBDevice callbacks
-+ */
-+
-+static void usbredir_handle_reset(USBDevice *udev)
-+{
-+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
-+
-+    DPRINTF("reset device\n");
-+    usbredirparser_send_reset(dev->parser);
-+    usbredirparser_do_write(dev->parser);
-+}
-+
-+static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
-+                                     uint8_t ep)
-+{
-+    int status, len;
-+
-+    if (!dev->endpoint[EP2I(ep)].iso_started &&
-+            !dev->endpoint[EP2I(ep)].iso_error) {
-+        struct usb_redir_start_iso_stream_header start_iso = {
-+            .endpoint = ep,
-+            /* TODO maybe do something with these depending on ep interval? */
-+            .pkts_per_urb = 32,
-+            .no_urbs = 3,
-+        };
-+        /* No id, we look at the ep when receiving a status back */
-+        usbredirparser_send_start_iso_stream(dev->parser, 0, &start_iso);
-+        usbredirparser_do_write(dev->parser);
-+        DPRINTF("iso stream started ep %02X\n", ep);
-+        dev->endpoint[EP2I(ep)].iso_started = 1;
-+    }
-+
-+    if (ep & USB_DIR_IN) {
-+        struct buf_packet *isop;
-+
-+        isop = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
-+        if (isop == NULL) {
-+            DPRINTF2("iso-token-in ep %02X, no isop\n", ep);
-+            /* Check iso_error for stream errors, otherwise its an underrun */
-+            status = dev->endpoint[EP2I(ep)].iso_error;
-+            dev->endpoint[EP2I(ep)].iso_error = 0;
-+            return usbredir_handle_status(dev, status, 0);
-+        }
-+        DPRINTF2("iso-token-in ep %02X status %d len %d\n", ep, isop->status,
-+                 isop->len);
-+
-+        status = isop->status;
-+        if (status != usb_redir_success) {
-+            bufp_free(dev, isop, ep);
-+            return usbredir_handle_status(dev, status, 0);
-+        }
-+
-+        len = isop->len;
-+        if (len > p->len) {
-+            ERROR("received iso data is larger then packet ep %02X\n", ep);
-+            bufp_free(dev, isop, ep);
-+            return USB_RET_NAK;
-+        }
-+        memcpy(p->data, isop->data, len);
-+        bufp_free(dev, isop, ep);
-+        return len;
-+    } else {
-+        /* If the stream was not started because of a pending error don't
-+           send the packet to the usb-host */
-+        if (dev->endpoint[EP2I(ep)].iso_started) {
-+            struct usb_redir_iso_packet_header iso_packet = {
-+                .endpoint = ep,
-+                .length = p->len
-+            };
-+            /* No id, we look at the ep when receiving a status back */
-+            usbredirparser_send_iso_packet(dev->parser, 0, &iso_packet,
-+                                           p->data, p->len);
-+            usbredirparser_do_write(dev->parser);
-+        }
-+        status = dev->endpoint[EP2I(ep)].iso_error;
-+        dev->endpoint[EP2I(ep)].iso_error = 0;
-+        DPRINTF2("iso-token-out ep %02X status %d len %d\n", ep, status,
-+                 p->len);
-+        return usbredir_handle_status(dev, status, p->len);
-+    }
-+}
-+
-+static void usbredir_stop_iso_stream(USBRedirDevice *dev, uint8_t ep)
-+{
-+    struct usb_redir_stop_iso_stream_header stop_iso_stream = {
-+        .endpoint = ep
-+    };
-+    if (dev->endpoint[EP2I(ep)].iso_started) {
-+        usbredirparser_send_stop_iso_stream(dev->parser, 0, &stop_iso_stream);
-+        DPRINTF("iso stream stopped ep %02X\n", ep);
-+        dev->endpoint[EP2I(ep)].iso_started = 0;
-+    }
-+    usbredir_free_bufpq(dev, ep);
-+}
-+
-+static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
-+                                      uint8_t ep)
-+{
-+    AsyncURB *aurb = async_alloc(dev, p);
-+    struct usb_redir_bulk_packet_header bulk_packet;
-+
-+    DPRINTF("bulk-out ep %02X len %d id %u\n", ep, p->len, aurb->packet_id);
-+
-+    bulk_packet.endpoint  = ep;
-+    bulk_packet.length    = p->len;
-+    bulk_packet.stream_id = 0;
-+    aurb->bulk_packet = bulk_packet;
-+
-+    if (ep & USB_DIR_IN) {
-+        usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,
-+                                        &bulk_packet, NULL, 0);
-+    } else {
-+        usbredir_log_data(dev, "bulk data out:", p->data, p->len);
-+        usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,
-+                                        &bulk_packet, p->data, p->len);
-+    }
-+    usbredirparser_do_write(dev->parser);
-+    return USB_RET_ASYNC;
-+}
-+
-+static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
-+                                           USBPacket *p, uint8_t ep)
-+{
-+    if (ep & USB_DIR_IN) {
-+        /* Input interrupt endpoint, buffered packet input */
-+        struct buf_packet *intp;
-+        int status, len;
-+
-+        if (!dev->endpoint[EP2I(ep)].interrupt_started &&
-+                !dev->endpoint[EP2I(ep)].interrupt_error) {
-+            struct usb_redir_start_interrupt_receiving_header start_int = {
-+                .endpoint = ep,
-+            };
-+            /* No id, we look at the ep when receiving a status back */
-+            usbredirparser_send_start_interrupt_receiving(dev->parser, 0,
-+                                                          &start_int);
-+            usbredirparser_do_write(dev->parser);
-+            DPRINTF("interrupt recv started ep %02X\n", ep);
-+            dev->endpoint[EP2I(ep)].interrupt_started = 1;
-+        }
-+
-+        intp = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
-+        if (intp == NULL) {
-+            DPRINTF2("interrupt-token-in ep %02X, no intp\n", ep);
-+            /* Check interrupt_error for stream errors */
-+            status = dev->endpoint[EP2I(ep)].interrupt_error;
-+            dev->endpoint[EP2I(ep)].interrupt_error = 0;
-+            return usbredir_handle_status(dev, status, 0);
-+        }
-+        DPRINTF("interrupt-token-in ep %02X status %d len %d\n", ep,
-+                intp->status, intp->len);
-+
-+        status = intp->status;
-+        if (status != usb_redir_success) {
-+            bufp_free(dev, intp, ep);
-+            return usbredir_handle_status(dev, status, 0);
-+        }
-+
-+        len = intp->len;
-+        if (len > p->len) {
-+            ERROR("received int data is larger then packet ep %02X\n", ep);
-+            bufp_free(dev, intp, ep);
-+            return USB_RET_NAK;
-+        }
-+        memcpy(p->data, intp->data, len);
-+        bufp_free(dev, intp, ep);
-+        return len;
-+    } else {
-+        /* Output interrupt endpoint, normal async operation */
-+        AsyncURB *aurb = async_alloc(dev, p);
-+        struct usb_redir_interrupt_packet_header interrupt_packet;
-+
-+        DPRINTF("interrupt-out ep %02X len %d id %u\n", ep, p->len,
-+                aurb->packet_id);
-+
-+        interrupt_packet.endpoint  = ep;
-+        interrupt_packet.length    = p->len;
-+        aurb->interrupt_packet     = interrupt_packet;
-+
-+        usbredir_log_data(dev, "interrupt data out:", p->data, p->len);
-+        usbredirparser_send_interrupt_packet(dev->parser, aurb->packet_id,
-+                                        &interrupt_packet, p->data, p->len);
-+        usbredirparser_do_write(dev->parser);
-+        return USB_RET_ASYNC;
-+    }
-+}
-+
-+static void usbredir_stop_interrupt_receiving(USBRedirDevice *dev,
-+    uint8_t ep)
-+{
-+    struct usb_redir_stop_interrupt_receiving_header stop_interrupt_recv = {
-+        .endpoint = ep
-+    };
-+    if (dev->endpoint[EP2I(ep)].interrupt_started) {
-+        usbredirparser_send_stop_interrupt_receiving(dev->parser, 0,
-+                                                     &stop_interrupt_recv);
-+        DPRINTF("interrupt recv stopped ep %02X\n", ep);
-+        dev->endpoint[EP2I(ep)].interrupt_started = 0;
-+    }
-+    usbredir_free_bufpq(dev, ep);
-+}
-+
-+static int usbredir_handle_data(USBDevice *udev, USBPacket *p)
-+{
-+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
-+    uint8_t ep;
-+
-+    ep = p->devep;
-+    if (p->pid == USB_TOKEN_IN) {
-+        ep |= USB_DIR_IN;
-+    }
-+
-+    switch (dev->endpoint[EP2I(ep)].type) {
-+    case USB_ENDPOINT_XFER_CONTROL:
-+        ERROR("handle_data called for control transfer on ep %02X\n", ep);
-+        return USB_RET_NAK;
-+    case USB_ENDPOINT_XFER_ISOC:
-+        return usbredir_handle_iso_data(dev, p, ep);
-+    case USB_ENDPOINT_XFER_BULK:
-+        return usbredir_handle_bulk_data(dev, p, ep);;
-+    case USB_ENDPOINT_XFER_INT:
-+        return usbredir_handle_interrupt_data(dev, p, ep);;
-+    default:
-+        ERROR("handle_data ep %02X has unknown type %d\n", ep,
-+              dev->endpoint[EP2I(ep)].type);
-+        return USB_RET_NAK;
-+    }
-+}
-+
-+static int usbredir_set_config(USBRedirDevice *dev, USBPacket *p,
-+                                int config)
-+{
-+    struct usb_redir_set_configuration_header set_config;
-+    AsyncURB *aurb = async_alloc(dev, p);
-+    int i;
-+
-+    DPRINTF("set config %d id %u\n", config, aurb->packet_id);
-+
-+    for (i = 0; i < MAX_ENDPOINTS; i++) {
-+        switch (dev->endpoint[i].type) {
-+        case USB_ENDPOINT_XFER_ISOC:
-+            usbredir_stop_iso_stream(dev, I2EP(i));
-+            break;
-+        case USB_ENDPOINT_XFER_INT:
-+            if (i & 0x10) {
-+                usbredir_stop_interrupt_receiving(dev, I2EP(i));
-+            }
-+            break;
-+        }
-+        usbredir_free_bufpq(dev, I2EP(i));
-+    }
-+
-+    set_config.configuration = config;
-+    usbredirparser_send_set_configuration(dev->parser, aurb->packet_id,
-+                                          &set_config);
-+    usbredirparser_do_write(dev->parser);
-+    return USB_RET_ASYNC;
-+}
-+
-+static int usbredir_get_config(USBRedirDevice *dev, USBPacket *p)
-+{
-+    AsyncURB *aurb = async_alloc(dev, p);
-+
-+    DPRINTF("get config id %u\n", aurb->packet_id);
-+
-+    aurb->get = 1;
-+    usbredirparser_send_get_configuration(dev->parser, aurb->packet_id);
-+    usbredirparser_do_write(dev->parser);
-+    return USB_RET_ASYNC;
-+}
-+
-+static int usbredir_set_interface(USBRedirDevice *dev, USBPacket *p,
-+                                   int interface, int alt)
-+{
-+    struct usb_redir_set_alt_setting_header set_alt;
-+    AsyncURB *aurb = async_alloc(dev, p);
-+    int i;
-+
-+    DPRINTF("set interface %d alt %d id %u\n", interface, alt,
-+            aurb->packet_id);
-+
-+    for (i = 0; i < MAX_ENDPOINTS; i++) {
-+        if (dev->endpoint[i].interface == interface) {
-+            switch (dev->endpoint[i].type) {
-+            case USB_ENDPOINT_XFER_ISOC:
-+                usbredir_stop_iso_stream(dev, I2EP(i));
-+                break;
-+            case USB_ENDPOINT_XFER_INT:
-+                if (i & 0x10) {
-+                    usbredir_stop_interrupt_receiving(dev, I2EP(i));
-+                }
-+                break;
-+            }
-+            usbredir_free_bufpq(dev, I2EP(i));
-+        }
-+    }
-+
-+    set_alt.interface = interface;
-+    set_alt.alt = alt;
-+    usbredirparser_send_set_alt_setting(dev->parser, aurb->packet_id,
-+                                        &set_alt);
-+    usbredirparser_do_write(dev->parser);
-+    return USB_RET_ASYNC;
-+}
-+
-+static int usbredir_get_interface(USBRedirDevice *dev, USBPacket *p,
-+                                   int interface)
-+{
-+    struct usb_redir_get_alt_setting_header get_alt;
-+    AsyncURB *aurb = async_alloc(dev, p);
-+
-+    DPRINTF("get interface %d id %u\n", interface, aurb->packet_id);
-+
-+    get_alt.interface = interface;
-+    aurb->get = 1;
-+    usbredirparser_send_get_alt_setting(dev->parser, aurb->packet_id,
-+                                        &get_alt);
-+    usbredirparser_do_write(dev->parser);
-+    return USB_RET_ASYNC;
-+}
-+
-+static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
-+        int request, int value, int index, int length, uint8_t *data)
-+{
-+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
-+    struct usb_redir_control_packet_header control_packet;
-+    AsyncURB *aurb;
-+
-+    /* Special cases for certain standard device requests */
-+    switch (request) {
-+    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
-+        DPRINTF("set address %d\n", value);
-+        dev->dev.addr = value;
-+        return 0;
-+    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
-+        return usbredir_set_config(dev, p, value & 0xff);
-+    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
-+        return usbredir_get_config(dev, p);
-+    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
-+        return usbredir_set_interface(dev, p, index, value);
-+    case InterfaceRequest | USB_REQ_GET_INTERFACE:
-+        return usbredir_get_interface(dev, p, index);
-+    }
-+
-+    /* "Normal" ctrl requests */
-+    aurb = async_alloc(dev, p);
-+
-+    /* Note request is (bRequestType << 8) | bRequest */
-+    DPRINTF("ctrl-out type 0x%x req 0x%x val 0x%x index %d len %d id %u\n",
-+            request >> 8, request & 0xff, value, index, length,
-+            aurb->packet_id);
-+
-+    control_packet.request     = request & 0xFF;
-+    control_packet.requesttype = request >> 8;
-+    control_packet.endpoint    = control_packet.requesttype & USB_DIR_IN;
-+    control_packet.value       = value;
-+    control_packet.index       = index;
-+    control_packet.length      = length;
-+    aurb->control_packet       = control_packet;
-+
-+    if (control_packet.requesttype & USB_DIR_IN) {
-+        usbredirparser_send_control_packet(dev->parser, aurb->packet_id,
-+                                           &control_packet, NULL, 0);
-+    } else {
-+        usbredir_log_data(dev, "ctrl data out:", data, length);
-+        usbredirparser_send_control_packet(dev->parser, aurb->packet_id,
-+                                           &control_packet, data, length);
-+    }
-+    usbredirparser_do_write(dev->parser);
-+    return USB_RET_ASYNC;
-+}
-+
-+/*
-+ * Close events can be triggered by usbredirparser_do_write which gets called
-+ * from within the USBDevice data / control packet callbacks and doing a
-+ * usb_detach from within these callbacks is not a good idea.
-+ *
-+ * So we use a bh handler to take care of close events. We also handle
-+ * open events from this callback to make sure that a close directly followed
-+ * by an open gets handled in the right order.
-+ */
-+static void usbredir_open_close_bh(void *opaque)
-+{
-+    USBRedirDevice *dev = opaque;
-+
-+    usbredir_device_disconnect(dev);
-+
-+    if (dev->parser) {
-+        usbredirparser_destroy(dev->parser);
-+        dev->parser = NULL;
-+    }
-+
-+    if (dev->cs->opened) {
-+        dev->parser = qemu_oom_check(usbredirparser_create());
-+        dev->parser->priv = dev;
-+        dev->parser->log_func = usbredir_log;
-+        dev->parser->read_func = usbredir_read;
-+        dev->parser->write_func = usbredir_write;
-+        dev->parser->device_connect_func = usbredir_device_connect;
-+        dev->parser->device_disconnect_func = usbredir_device_disconnect;
-+        dev->parser->interface_info_func = usbredir_interface_info;
-+        dev->parser->ep_info_func = usbredir_ep_info;
-+        dev->parser->configuration_status_func = usbredir_configuration_status;
-+        dev->parser->alt_setting_status_func = usbredir_alt_setting_status;
-+        dev->parser->iso_stream_status_func = usbredir_iso_stream_status;
-+        dev->parser->interrupt_receiving_status_func =
-+            usbredir_interrupt_receiving_status;
-+        dev->parser->bulk_streams_status_func = usbredir_bulk_streams_status;
-+        dev->parser->control_packet_func = usbredir_control_packet;
-+        dev->parser->bulk_packet_func = usbredir_bulk_packet;
-+        dev->parser->iso_packet_func = usbredir_iso_packet;
-+        dev->parser->interrupt_packet_func = usbredir_interrupt_packet;
-+        dev->read_buf = NULL;
-+        dev->read_buf_size = 0;
-+        usbredirparser_init(dev->parser, VERSION, NULL, 0, 0);
-+        usbredirparser_do_write(dev->parser);
-+    }
-+}
-+
-+static void usbredir_do_attach(void *opaque)
-+{
-+    USBRedirDevice *dev = opaque;
-+
-+    usb_device_attach(&dev->dev);
-+}
-+
-+/*
-+ * chardev callbacks
-+ */
-+
-+static int usbredir_chardev_can_read(void *opaque)
-+{
-+    USBRedirDevice *dev = opaque;
-+
-+    if (dev->parser) {
-+        /* usbredir_parser_do_read will consume *all* data we give it */
-+        return 1024 * 1024;
-+    } else {
-+        /* usbredir_open_close_bh hasn't handled the open event yet */
-+        return 0;
-+    }
-+}
-+
-+static void usbredir_chardev_read(void *opaque, const uint8_t *buf, int size)
-+{
-+    USBRedirDevice *dev = opaque;
-+
-+    /* No recursion allowed! */
-+    assert(dev->read_buf == NULL);
-+
-+    dev->read_buf = buf;
-+    dev->read_buf_size = size;
-+
-+    usbredirparser_do_read(dev->parser);
-+    /* Send any acks, etc. which may be queued now */
-+    usbredirparser_do_write(dev->parser);
-+}
-+
-+static void usbredir_chardev_event(void *opaque, int event)
-+{
-+    USBRedirDevice *dev = opaque;
-+
-+    switch (event) {
-+    case CHR_EVENT_OPENED:
-+    case CHR_EVENT_CLOSED:
-+        qemu_bh_schedule(dev->open_close_bh);
-+        break;
-+    }
-+}
-+
-+/*
-+ * init + destroy
-+ */
-+
-+static int usbredir_initfn(USBDevice *udev)
-+{
-+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
-+    int i;
-+
-+    if (dev->cs == NULL) {
-+        qerror_report(QERR_MISSING_PARAMETER, "chardev");
-+        return -1;
-+    }
-+
-+    dev->open_close_bh = qemu_bh_new(usbredir_open_close_bh, dev);
-+    dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
-+
-+    QTAILQ_INIT(&dev->asyncq);
-+    for (i = 0; i < MAX_ENDPOINTS; i++) {
-+        QTAILQ_INIT(&dev->endpoint[i].bufpq);
-+    }
-+
-+    /* We'll do the attach once we receive the speed from the usb-host */
-+    udev->auto_attach = 0;
-+
-+    qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
-+                          usbredir_chardev_read, usbredir_chardev_event, dev);
-+
-+    return 0;
-+}
-+
-+static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
-+{
-+    AsyncURB *aurb, *next_aurb;
-+    int i;
-+
-+    QTAILQ_FOREACH_SAFE(aurb, &dev->asyncq, next, next_aurb) {
-+        async_free(dev, aurb);
-+    }
-+    for (i = 0; i < MAX_ENDPOINTS; i++) {
-+        usbredir_free_bufpq(dev, I2EP(i));
-+    }
-+}
-+
-+static void usbredir_handle_destroy(USBDevice *udev)
-+{
-+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
-+
-+    qemu_chr_close(dev->cs);
-+    /* Note must be done after qemu_chr_close, as that causes a close event */
-+    qemu_bh_delete(dev->open_close_bh);
-+
-+    qemu_del_timer(dev->attach_timer);
-+    qemu_free_timer(dev->attach_timer);
-+
-+    usbredir_cleanup_device_queues(dev);
-+
-+    if (dev->parser) {
-+        usbredirparser_destroy(dev->parser);
-+    }
-+}
-+
-+/*
-+ * usbredirparser packet complete callbacks
-+ */
-+
-+static int usbredir_handle_status(USBRedirDevice *dev,
-+                                       int status, int actual_len)
-+{
-+    switch (status) {
-+    case usb_redir_success:
-+        return actual_len;
-+    case usb_redir_stall:
-+        return USB_RET_STALL;
-+    case usb_redir_cancelled:
-+        WARNING("returning cancelled packet to HC?\n");
-+    case usb_redir_inval:
-+    case usb_redir_ioerror:
-+    case usb_redir_timeout:
-+    default:
-+        return USB_RET_NAK;
-+    }
-+}
-+
-+static void usbredir_device_connect(void *priv,
-+    struct usb_redir_device_connect_header *device_connect)
-+{
-+    USBRedirDevice *dev = priv;
-+
-+    switch (device_connect->speed) {
-+    case usb_redir_speed_low:
-+        DPRINTF("attaching low speed device\n");
-+        dev->dev.speed = USB_SPEED_LOW;
-+        break;
-+    case usb_redir_speed_full:
-+        DPRINTF("attaching full speed device\n");
-+        dev->dev.speed = USB_SPEED_FULL;
-+        break;
-+    case usb_redir_speed_high:
-+        DPRINTF("attaching high speed device\n");
-+        dev->dev.speed = USB_SPEED_HIGH;
-+        break;
-+    case usb_redir_speed_super:
-+        DPRINTF("attaching super speed device\n");
-+        dev->dev.speed = USB_SPEED_SUPER;
-+        break;
-+    default:
-+        DPRINTF("attaching unknown speed device, assuming full speed\n");
-+        dev->dev.speed = USB_SPEED_FULL;
-+    }
-+    dev->dev.speedmask = (1 << dev->dev.speed);
-+    qemu_mod_timer(dev->attach_timer, dev->next_attach_time);
-+}
-+
-+static void usbredir_device_disconnect(void *priv)
-+{
-+    USBRedirDevice *dev = priv;
-+
-+    /* Stop any pending attaches */
-+    qemu_del_timer(dev->attach_timer);
-+
-+    if (dev->dev.attached) {
-+        usb_device_detach(&dev->dev);
-+        usbredir_cleanup_device_queues(dev);
-+        /*
-+         * Delay next usb device attach to give the guest a chance to see
-+         * see the detach / attach in case of quick close / open succession
-+         */
-+        dev->next_attach_time = qemu_get_clock_ms(vm_clock) + 200;
-+    }
-+}
-+
-+static void usbredir_interface_info(void *priv,
-+    struct usb_redir_interface_info_header *interface_info)
-+{
-+    /* The intention is to allow specifying acceptable interface classes
-+       for redirection on the cmdline and in the future verify this here,
-+       and disconnect (or never connect) the device if a not accepted
-+       interface class is detected */
-+}
-+
-+static void usbredir_ep_info(void *priv,
-+    struct usb_redir_ep_info_header *ep_info)
-+{
-+    USBRedirDevice *dev = priv;
-+    int i;
-+
-+    for (i = 0; i < MAX_ENDPOINTS; i++) {
-+        dev->endpoint[i].type = ep_info->type[i];
-+        dev->endpoint[i].interval = ep_info->interval[i];
-+        dev->endpoint[i].interface = ep_info->interface[i];
-+        if (dev->endpoint[i].type != usb_redir_type_invalid) {
-+            DPRINTF("ep: %02X type: %d interface: %d\n", I2EP(i),
-+                    dev->endpoint[i].type, dev->endpoint[i].interface);
-+        }
-+    }
-+}
-+
-+static void usbredir_configuration_status(void *priv, uint32_t id,
-+    struct usb_redir_configuration_status_header *config_status)
-+{
-+    USBRedirDevice *dev = priv;
-+    AsyncURB *aurb;
-+    int len = 0;
-+
-+    DPRINTF("set config status %d config %d id %u\n", config_status->status,
-+            config_status->configuration, id);
-+
-+    aurb = async_find(dev, id);
-+    if (!aurb) {
-+        return;
-+    }
-+    if (aurb->packet) {
-+        if (aurb->get) {
-+            dev->dev.data_buf[0] = config_status->configuration;
-+            len = 1;
-+        }
-+        aurb->packet->len =
-+            usbredir_handle_status(dev, config_status->status, len);
-+        usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
-+    }
-+    async_free(dev, aurb);
-+}
-+
-+static void usbredir_alt_setting_status(void *priv, uint32_t id,
-+    struct usb_redir_alt_setting_status_header *alt_setting_status)
-+{
-+    USBRedirDevice *dev = priv;
-+    AsyncURB *aurb;
-+    int len = 0;
-+
-+    DPRINTF("alt status %d intf %d alt %d id: %u\n",
-+            alt_setting_status->status,
-+            alt_setting_status->interface,
-+            alt_setting_status->alt, id);
-+
-+    aurb = async_find(dev, id);
-+    if (!aurb) {
-+        return;
-+    }
-+    if (aurb->packet) {
-+        if (aurb->get) {
-+            dev->dev.data_buf[0] = alt_setting_status->alt;
-+            len = 1;
-+        }
-+        aurb->packet->len =
-+            usbredir_handle_status(dev, alt_setting_status->status, len);
-+        usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
-+    }
-+    async_free(dev, aurb);
-+}
-+
-+static void usbredir_iso_stream_status(void *priv, uint32_t id,
-+    struct usb_redir_iso_stream_status_header *iso_stream_status)
-+{
-+    USBRedirDevice *dev = priv;
-+    uint8_t ep = iso_stream_status->endpoint;
-+
-+    DPRINTF("iso status %d ep %02X id %u\n", iso_stream_status->status,
-+            ep, id);
-+
-+    dev->endpoint[EP2I(ep)].iso_error = iso_stream_status->status;
-+    if (iso_stream_status->status == usb_redir_stall) {
-+        DPRINTF("iso stream stopped by peer ep %02X\n", ep);
-+        dev->endpoint[EP2I(ep)].iso_started = 0;
-+    }
-+}
-+
-+static void usbredir_interrupt_receiving_status(void *priv, uint32_t id,
-+    struct usb_redir_interrupt_receiving_status_header
-+    *interrupt_receiving_status)
-+{
-+    USBRedirDevice *dev = priv;
-+    uint8_t ep = interrupt_receiving_status->endpoint;
-+
-+    DPRINTF("interrupt recv status %d ep %02X id %u\n",
-+            interrupt_receiving_status->status, ep, id);
-+
-+    dev->endpoint[EP2I(ep)].interrupt_error =
-+        interrupt_receiving_status->status;
-+    if (interrupt_receiving_status->status == usb_redir_stall) {
-+        DPRINTF("interrupt receiving stopped by peer ep %02X\n", ep);
-+        dev->endpoint[EP2I(ep)].interrupt_started = 0;
-+    }
-+}
-+
-+static void usbredir_bulk_streams_status(void *priv, uint32_t id,
-+    struct usb_redir_bulk_streams_status_header *bulk_streams_status)
-+{
-+}
-+
-+static void usbredir_control_packet(void *priv, uint32_t id,
-+    struct usb_redir_control_packet_header *control_packet,
-+    uint8_t *data, int data_len)
-+{
-+    USBRedirDevice *dev = priv;
-+    int len = control_packet->length;
-+    AsyncURB *aurb;
-+
-+    DPRINTF("ctrl-in status %d len %d id %u\n", control_packet->status,
-+            len, id);
-+
-+    aurb = async_find(dev, id);
-+    if (!aurb) {
-+        free(data);
-+        return;
-+    }
-+
-+    aurb->control_packet.status = control_packet->status;
-+    aurb->control_packet.length = control_packet->length;
-+    if (memcmp(&aurb->control_packet, control_packet,
-+               sizeof(*control_packet))) {
-+        ERROR("return control packet mismatch, please report this!\n");
-+        len = USB_RET_NAK;
-+    }
-+
-+    if (aurb->packet) {
-+        len = usbredir_handle_status(dev, control_packet->status, len);
-+        if (len > 0) {
-+            usbredir_log_data(dev, "ctrl data in:", data, data_len);
-+            if (data_len <= sizeof(dev->dev.data_buf)) {
-+                memcpy(dev->dev.data_buf, data, data_len);
-+            } else {
-+                ERROR("ctrl buffer too small (%d > %zu)\n",
-+                      data_len, sizeof(dev->dev.data_buf));
-+                len = USB_RET_STALL;
-+            }
-+        }
-+        aurb->packet->len = len;
-+        usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
-+    }
-+    async_free(dev, aurb);
-+    free(data);
-+}
-+
-+static void usbredir_bulk_packet(void *priv, uint32_t id,
-+    struct usb_redir_bulk_packet_header *bulk_packet,
-+    uint8_t *data, int data_len)
-+{
-+    USBRedirDevice *dev = priv;
-+    uint8_t ep = bulk_packet->endpoint;
-+    int len = bulk_packet->length;
-+    AsyncURB *aurb;
-+
-+    DPRINTF("bulk-in status %d ep %02X len %d id %u\n", bulk_packet->status,
-+            ep, len, id);
-+
-+    aurb = async_find(dev, id);
-+    if (!aurb) {
-+        free(data);
-+        return;
-+    }
-+
-+    if (aurb->bulk_packet.endpoint != bulk_packet->endpoint ||
-+            aurb->bulk_packet.stream_id != bulk_packet->stream_id) {
-+        ERROR("return bulk packet mismatch, please report this!\n");
-+        len = USB_RET_NAK;
-+    }
-+
-+    if (aurb->packet) {
-+        len = usbredir_handle_status(dev, bulk_packet->status, len);
-+        if (len > 0) {
-+            usbredir_log_data(dev, "bulk data in:", data, data_len);
-+            if (data_len <= aurb->packet->len) {
-+                memcpy(aurb->packet->data, data, data_len);
-+            } else {
-+                ERROR("bulk buffer too small (%d > %d)\n", data_len,
-+                      aurb->packet->len);
-+                len = USB_RET_STALL;
-+            }
-+        }
-+        aurb->packet->len = len;
-+        usb_packet_complete(&dev->dev, aurb->packet);
-+    }
-+    async_free(dev, aurb);
-+    free(data);
-+}
-+
-+static void usbredir_iso_packet(void *priv, uint32_t id,
-+    struct usb_redir_iso_packet_header *iso_packet,
-+    uint8_t *data, int data_len)
-+{
-+    USBRedirDevice *dev = priv;
-+    uint8_t ep = iso_packet->endpoint;
-+
-+    DPRINTF2("iso-in status %d ep %02X len %d id %u\n", iso_packet->status, ep,
-+             data_len, id);
-+
-+    if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_ISOC) {
-+        ERROR("received iso packet for non iso endpoint %02X\n", ep);
-+        free(data);
-+        return;
-+    }
-+
-+    if (dev->endpoint[EP2I(ep)].iso_started == 0) {
-+        DPRINTF("received iso packet for non started stream ep %02X\n", ep);
-+        free(data);
-+        return;
-+    }
-+
-+    /* bufp_alloc also adds the packet to the ep queue */
-+    bufp_alloc(dev, data, data_len, iso_packet->status, ep);
-+}
-+
-+static void usbredir_interrupt_packet(void *priv, uint32_t id,
-+    struct usb_redir_interrupt_packet_header *interrupt_packet,
-+    uint8_t *data, int data_len)
-+{
-+    USBRedirDevice *dev = priv;
-+    uint8_t ep = interrupt_packet->endpoint;
-+
-+    DPRINTF("interrupt-in status %d ep %02X len %d id %u\n",
-+            interrupt_packet->status, ep, data_len, id);
-+
-+    if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_INT) {
-+        ERROR("received int packet for non interrupt endpoint %02X\n", ep);
-+        free(data);
-+        return;
-+    }
-+
-+    if (ep & USB_DIR_IN) {
-+        if (dev->endpoint[EP2I(ep)].interrupt_started == 0) {
-+            DPRINTF("received int packet while not started ep %02X\n", ep);
-+            free(data);
-+            return;
-+        }
-+
-+        /* bufp_alloc also adds the packet to the ep queue */
-+        bufp_alloc(dev, data, data_len, interrupt_packet->status, ep);
-+    } else {
-+        int len = interrupt_packet->length;
-+
-+        AsyncURB *aurb = async_find(dev, id);
-+        if (!aurb) {
-+            return;
-+        }
-+
-+        if (aurb->interrupt_packet.endpoint != interrupt_packet->endpoint) {
-+            ERROR("return int packet mismatch, please report this!\n");
-+            len = USB_RET_NAK;
-+        }
-+
-+        if (aurb->packet) {
-+            aurb->packet->len = usbredir_handle_status(dev,
-+                                               interrupt_packet->status, len);
-+            usb_packet_complete(&dev->dev, aurb->packet);
-+        }
-+        async_free(dev, aurb);
-+    }
-+}
-+
-+static struct USBDeviceInfo usbredir_dev_info = {
-+    .product_desc   = "USB Redirection Device",
-+    .qdev.name      = "usb-redir",
-+    .qdev.size      = sizeof(USBRedirDevice),
-+    .init           = usbredir_initfn,
-+    .handle_destroy = usbredir_handle_destroy,
-+    .handle_packet  = usb_generic_handle_packet,
-+    .cancel_packet  = usbredir_cancel_packet,
-+    .handle_reset   = usbredir_handle_reset,
-+    .handle_data    = usbredir_handle_data,
-+    .handle_control = usbredir_handle_control,
-+    .qdev.props     = (Property[]) {
-+        DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
-+        DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0),
-+        DEFINE_PROP_END_OF_LIST(),
-+    },
-+};
-+
-+static void usbredir_register_devices(void)
-+{
-+    usb_qdev_register(&usbredir_dev_info);
-+}
-+device_init(usbredir_register_devices);
--- 
-1.7.5.1
-
diff --git a/0025-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch b/0025-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch
deleted file mode 100644
index 2632655..0000000
--- a/0025-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From d24514c807c4cddfe5f919bd01cb1a9cd3f21b10 Mon Sep 17 00:00:00 2001
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 21:57:47 +0100
-Subject: [PATCH 25/35] char: Split out tcp socket close code in a separate
- function
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
----
- qemu-char.c |   25 ++++++++++++++++---------
- 1 files changed, 16 insertions(+), 9 deletions(-)
-
-diff --git a/qemu-char.c b/qemu-char.c
-index fb13b28..75efa60 100644
---- a/qemu-char.c
-+++ b/qemu-char.c
-@@ -1917,6 +1917,21 @@ typedef struct {
- 
- static void tcp_chr_accept(void *opaque);
- 
-+static void tcp_closed(void *opaque)
-+{
-+    CharDriverState *chr = opaque;
-+    TCPCharDriver *s = chr->opaque;
-+
-+    s->connected = 0;
-+    if (s->listen_fd >= 0) {
-+        qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
-+    }
-+    qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
-+    closesocket(s->fd);
-+    s->fd = -1;
-+    qemu_chr_event(chr, CHR_EVENT_CLOSED);
-+}
-+
- static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
- {
-     TCPCharDriver *s = chr->opaque;
-@@ -2067,15 +2082,7 @@ static void tcp_chr_read(void *opaque)
-         len = s->max_size;
-     size = tcp_chr_recv(chr, (void *)buf, len);
-     if (size == 0) {
--        /* connection closed */
--        s->connected = 0;
--        if (s->listen_fd >= 0) {
--            qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
--        }
--        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
--        closesocket(s->fd);
--        s->fd = -1;
--        qemu_chr_event(chr, CHR_EVENT_CLOSED);
-+        tcp_closed(chr);
-     } else if (size > 0) {
-         if (s->do_telnetopt)
-             tcp_chr_process_IAC_bytes(chr, s, buf, &size);
--- 
-1.7.5.1
-
diff --git a/0026-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch b/0026-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch
deleted file mode 100644
index 7433073..0000000
--- a/0026-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch
+++ /dev/null
@@ -1,882 +0,0 @@
-From 7a78607683a3c3a25ab715d6a5e137be9cf29e66 Mon Sep 17 00:00:00 2001
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 20:31:45 +0100
-Subject: [PATCH 26/35] char: Add a QemuChrHandlers struct to initialise
- chardev handlers
-
-Instead of passing each handler in the qemu_add_handlers() function,
-create a struct of handlers that can be passed to the function instead.
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
----
- gdbstub.c               |    9 +++++++--
- hw/ccid-card-passthru.c |   11 +++++++----
- hw/debugcon.c           |    2 +-
- hw/escc.c               |    9 +++++++--
- hw/etraxfs_ser.c        |   13 +++++++++----
- hw/grlib_apbuart.c      |   12 +++++++-----
- hw/ivshmem.c            |   28 ++++++++++++++++++++++------
- hw/lm32_juart.c         |    8 +++++++-
- hw/lm32_uart.c          |    8 +++++++-
- hw/mcf_uart.c           |    9 +++++++--
- hw/milkymist-uart.c     |    8 +++++++-
- hw/pl011.c              |    9 +++++++--
- hw/pxa2xx.c             |   13 +++++++++----
- hw/serial.c             |    9 +++++++--
- hw/sh_serial.c          |   12 +++++++++---
- hw/spapr_vty.c          |    8 ++++++--
- hw/strongarm.c          |   12 +++++++-----
- hw/syborg_serial.c      |    9 +++++++--
- hw/usb-serial.c         |    9 +++++++--
- hw/virtio-console.c     |   11 ++++++++---
- hw/xen_console.c        |   16 +++++++++++-----
- hw/xilinx_uartlite.c    |   11 +++++++++--
- monitor.c               |   18 ++++++++++++++----
- net/slirp.c             |    8 ++++++--
- qemu-char.c             |   32 ++++++++++++++++++++++----------
- qemu-char.h             |   13 +++++++++----
- usb-redir.c             |    9 +++++++--
- 27 files changed, 233 insertions(+), 83 deletions(-)
-
-diff --git a/gdbstub.c b/gdbstub.c
-index c085a5a..0ff61cb 100644
---- a/gdbstub.c
-+++ b/gdbstub.c
-@@ -2739,6 +2739,12 @@ static void gdb_sigterm_handler(int signal)
- }
- #endif
- 
-+static const QemuChrHandlers gdb_handlers = {
-+    .fd_can_read = gdb_chr_can_receive,
-+    .fd_read = gdb_chr_receive,
-+    .fd_event = gdb_chr_event,
-+};
-+
- int gdbserver_start(const char *device)
- {
-     GDBState *s;
-@@ -2768,8 +2774,7 @@ int gdbserver_start(const char *device)
-         if (!chr)
-             return -1;
- 
--        qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
--                              gdb_chr_event, NULL);
-+        qemu_chr_add_handlers(chr, &gdb_handlers, NULL);
-     }
- 
-     s = gdbserver_state;
-diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
-index 28eb9d1..1dee6f7 100644
---- a/hw/ccid-card-passthru.c
-+++ b/hw/ccid-card-passthru.c
-@@ -273,6 +273,12 @@ static const uint8_t *passthru_get_atr(CCIDCardState *base, uint32_t *len)
-     return card->atr;
- }
- 
-+static const QemuChrHandlers passthru_handlers = {
-+    .fd_can_read = ccid_card_vscard_can_read,
-+    .fd_read = ccid_card_vscard_read,
-+    .fd_event = ccid_card_vscard_event,
-+};
-+
- static int passthru_initfn(CCIDCardState *base)
- {
-     PassthruState *card = DO_UPCAST(PassthruState, base, base);
-@@ -281,10 +287,7 @@ static int passthru_initfn(CCIDCardState *base)
-     card->vscard_in_hdr = 0;
-     if (card->cs) {
-         DPRINTF(card, D_INFO, "initing chardev\n");
--        qemu_chr_add_handlers(card->cs,
--            ccid_card_vscard_can_read,
--            ccid_card_vscard_read,
--            ccid_card_vscard_event, card);
-+        qemu_chr_add_handlers(card->cs, &passthru_handlers, card);
-         ccid_card_vscard_send_init(card);
-     } else {
-         error_report("missing chardev");
-diff --git a/hw/debugcon.c b/hw/debugcon.c
-index 5ee6821..e79a595 100644
---- a/hw/debugcon.c
-+++ b/hw/debugcon.c
-@@ -73,7 +73,7 @@ static void debugcon_init_core(DebugconState *s)
-         exit(1);
-     }
- 
--    qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s);
-+    qemu_chr_add_handlers(s->chr, NULL, s);
- }
- 
- static int debugcon_isa_initfn(ISADevice *dev)
-diff --git a/hw/escc.c b/hw/escc.c
-index f6fd919..dfa329a 100644
---- a/hw/escc.c
-+++ b/hw/escc.c
-@@ -898,6 +898,12 @@ void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
-     sysbus_mmio_map(s, 0, base);
- }
- 
-+static const QemuChrHandlers serial_handlers = {
-+    .fd_can_read = serial_can_receive,
-+    .fd_read = serial_receive1,
-+    .fd_event = serial_event,
-+};
-+
- static int escc_init1(SysBusDevice *dev)
- {
-     SerialState *s = FROM_SYSBUS(SerialState, dev);
-@@ -911,8 +917,7 @@ static int escc_init1(SysBusDevice *dev)
-         s->chn[i].chn = 1 - i;
-         s->chn[i].clock = s->frequency / 2;
-         if (s->chn[i].chr) {
--            qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
--                                  serial_receive1, serial_event, &s->chn[i]);
-+            qemu_chr_add_handlers(s->chn[i].chr, &serial_handlers, &s->chn[i]);
-         }
-     }
-     s->chn[0].otherchn = &s->chn[1];
-diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
-index b917d4d..ebbad77 100644
---- a/hw/etraxfs_ser.c
-+++ b/hw/etraxfs_ser.c
-@@ -202,6 +202,12 @@ static void etraxfs_ser_reset(DeviceState *d)
- 
- }
- 
-+static const QemuChrHandlers serial_handlers = {
-+    .fd_can_read = serial_can_receive,
-+    .fd_read = serial_receive,
-+    .fd_event = serial_event,
-+};
-+
- static int etraxfs_ser_init(SysBusDevice *dev)
- {
-     struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
-@@ -212,10 +218,9 @@ static int etraxfs_ser_init(SysBusDevice *dev)
-                                       DEVICE_NATIVE_ENDIAN);
-     sysbus_init_mmio(dev, R_MAX * 4, ser_regs);
-     s->chr = qdev_init_chardev(&dev->qdev);
--    if (s->chr)
--        qemu_chr_add_handlers(s->chr,
--                      serial_can_receive, serial_receive,
--                      serial_event, s);
-+    if (s->chr) {
-+        qemu_chr_add_handlers(s->chr, &serial_handlers, s);
-+    }
-     return 0;
- }
- 
-diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c
-index 169a56e..310687b 100644
---- a/hw/grlib_apbuart.c
-+++ b/hw/grlib_apbuart.c
-@@ -144,16 +144,18 @@ static CPUWriteMemoryFunc * const grlib_apbuart_write[] = {
-     NULL, NULL, grlib_apbuart_writel,
- };
- 
-+static const QemuChrHandlers grlib_handlers = {
-+    .fd_can_read = grlib_apbuart_can_receive,
-+    .fd_read = grlib_apbuart_receive,
-+    .fd_event = grlib_apbuart_event,
-+};
-+
- static int grlib_apbuart_init(SysBusDevice *dev)
- {
-     UART *uart      = FROM_SYSBUS(typeof(*uart), dev);
-     int   uart_regs = 0;
- 
--    qemu_chr_add_handlers(uart->chr,
--                          grlib_apbuart_can_receive,
--                          grlib_apbuart_receive,
--                          grlib_apbuart_event,
--                          uart);
-+    qemu_chr_add_handlers(uart->chr, &grlib_handlers, uart);
- 
-     sysbus_init_irq(dev, &uart->irq);
- 
-diff --git a/hw/ivshmem.c b/hw/ivshmem.c
-index 3055dd2..4f59575 100644
---- a/hw/ivshmem.c
-+++ b/hw/ivshmem.c
-@@ -312,6 +312,18 @@ static void fake_irqfd(void *opaque, const uint8_t *buf, int size) {
-     msix_notify(pdev, entry->vector);
- }
- 
-+static const QemuChrHandlers ivshmem_handlers = {
-+    .fd_can_read = ivshmem_can_receive,
-+    .fd_read = ivshmem_receive,
-+    .fd_event = ivshmem_event,
-+};
-+
-+static const QemuChrHandlers ivshmem_msi_handlers = {
-+    .fd_can_read = ivshmem_can_receive,
-+    .fd_read = fake_irqfd,
-+    .fd_event = ivshmem_event,
-+};
-+
- static CharDriverState* create_eventfd_chr_device(void * opaque, int eventfd,
-                                                                     int vector)
- {
-@@ -331,11 +343,10 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, int eventfd,
-         s->eventfd_table[vector].pdev = &s->dev;
-         s->eventfd_table[vector].vector = vector;
- 
--        qemu_chr_add_handlers(chr, ivshmem_can_receive, fake_irqfd,
--                      ivshmem_event, &s->eventfd_table[vector]);
-+        qemu_chr_add_handlers(chr, &ivshmem_msi_handlers,
-+                              &s->eventfd_table[vector]);
-     } else {
--        qemu_chr_add_handlers(chr, ivshmem_can_receive, ivshmem_receive,
--                      ivshmem_event, s);
-+        qemu_chr_add_handlers(chr, &ivshmem_handlers, s);
-     }
- 
-     return chr;
-@@ -666,6 +677,12 @@ static int ivshmem_load(QEMUFile* f, void *opaque, int version_id)
-     return 0;
- }
- 
-+static const QemuChrHandlers ivshmem_server_handlers = {
-+    .fd_can_read = ivshmem_can_receive,
-+    .fd_read = ivshmem_read,
-+    .fd_event = ivshmem_event,
-+};
-+
- static int pci_ivshmem_init(PCIDevice *dev)
- {
-     IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev);
-@@ -749,8 +766,7 @@ static int pci_ivshmem_init(PCIDevice *dev)
- 
-         s->eventfd_chr = qemu_mallocz(s->vectors * sizeof(CharDriverState *));
- 
--        qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive, ivshmem_read,
--                     ivshmem_event, s);
-+        qemu_chr_add_handlers(s->server_chr, &ivshmem_server_handlers, s);
-     } else {
-         /* just map the file immediately, we're not using a server */
-         int fd;
-diff --git a/hw/lm32_juart.c b/hw/lm32_juart.c
-index fddcf7e..12dd1e8 100644
---- a/hw/lm32_juart.c
-+++ b/hw/lm32_juart.c
-@@ -110,13 +110,19 @@ static void juart_reset(DeviceState *d)
-     s->jrx = 0;
- }
- 
-+static const QemuChrHandlers juart_handlers = {
-+    .fd_can_read = juart_can_rx,
-+    .fd_read = juart_rx,
-+    .fd_event = juart_event,
-+};
-+
- static int lm32_juart_init(SysBusDevice *dev)
- {
-     LM32JuartState *s = FROM_SYSBUS(typeof(*s), dev);
- 
-     s->chr = qdev_init_chardev(&dev->qdev);
-     if (s->chr) {
--        qemu_chr_add_handlers(s->chr, juart_can_rx, juart_rx, juart_event, s);
-+        qemu_chr_add_handlers(s->chr, juart_handlers, s);
-     }
- 
-     return 0;
-diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c
-index 09090e9..5438660 100644
---- a/hw/lm32_uart.c
-+++ b/hw/lm32_uart.c
-@@ -242,6 +242,12 @@ static void uart_reset(DeviceState *d)
-     s->regs[R_LSR] = LSR_THRE | LSR_TEMT;
- }
- 
-+static const QemuChrHandlers uart_handlers = {
-+    .fd_can_read = uart_can_rx,
-+    .fd_read = uart_rx,
-+    .fd_event = uart_event,
-+};
-+
- static int lm32_uart_init(SysBusDevice *dev)
- {
-     LM32UartState *s = FROM_SYSBUS(typeof(*s), dev);
-@@ -255,7 +261,7 @@ static int lm32_uart_init(SysBusDevice *dev)
- 
-     s->chr = qdev_init_chardev(&dev->qdev);
-     if (s->chr) {
--        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
-+        qemu_chr_add_handlers(s->chr, uart_handlers, s);
-     }
- 
-     return 0;
-diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c
-index db57096..9928c11 100644
---- a/hw/mcf_uart.c
-+++ b/hw/mcf_uart.c
-@@ -268,6 +268,12 @@ static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size)
-     mcf_uart_push_byte(s, buf[0]);
- }
- 
-+static const QemuChrHandlers mcf_uart_handlers = {
-+    .fd_can_read = mcf_uart_can_receive,
-+    .fd_read = mcf_uart_receive,
-+    .fd_event = mcf_uart_event,
-+};
-+
- void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
- {
-     mcf_uart_state *s;
-@@ -276,8 +282,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
-     s->chr = chr;
-     s->irq = irq;
-     if (chr) {
--        qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
--                              mcf_uart_event, s);
-+        qemu_chr_add_handlers(chr, &mcf_uart_handlers, s);
-     }
-     mcf_uart_reset(s);
-     return s;
-diff --git a/hw/milkymist-uart.c b/hw/milkymist-uart.c
-index 56c90da..4412b1b 100644
---- a/hw/milkymist-uart.c
-+++ b/hw/milkymist-uart.c
-@@ -133,6 +133,12 @@ static void milkymist_uart_reset(DeviceState *d)
-     }
- }
- 
-+static const QemuChrHandlers uart_handlers = {
-+    .fd_can_read = uart_can_rx,
-+    .fd_read = uart_rx,
-+    .fd_event = uart_event,
-+};
-+
- static int milkymist_uart_init(SysBusDevice *dev)
- {
-     MilkymistUartState *s = FROM_SYSBUS(typeof(*s), dev);
-@@ -147,7 +153,7 @@ static int milkymist_uart_init(SysBusDevice *dev)
- 
-     s->chr = qdev_init_chardev(&dev->qdev);
-     if (s->chr) {
--        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
-+        qemu_chr_add_handlers(s->chr, uart_handlers, s);
-     }
- 
-     return 0;
-diff --git a/hw/pl011.c b/hw/pl011.c
-index 3b94b14..7b4f3ae 100644
---- a/hw/pl011.c
-+++ b/hw/pl011.c
-@@ -260,6 +260,12 @@ static const VMStateDescription vmstate_pl011 = {
-     }
- };
- 
-+static const QemuChrHandlers pl011_handlers = {
-+    .fd_can_read = pl011_can_receive,
-+    .fd_read = pl011_receive,
-+    .fd_event = pl011_event,
-+};
-+
- static int pl011_init(SysBusDevice *dev, const unsigned char *id)
- {
-     int iomemtype;
-@@ -278,8 +284,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
-     s->cr = 0x300;
-     s->flags = 0x90;
-     if (s->chr) {
--        qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
--                              pl011_event, s);
-+        qemu_chr_add_handlers(s->chr, &pl011_handlers, s);
-     }
-     vmstate_register(&dev->qdev, -1, &vmstate_pl011, s);
-     return 0;
-diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
-index ac5d95d..779081c 100644
---- a/hw/pxa2xx.c
-+++ b/hw/pxa2xx.c
-@@ -2019,6 +2019,12 @@ static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id)
-     return 0;
- }
- 
-+static const QemuChrHandlers pxa2xx_handlers = {
-+    .fd_can_read = pxa2xx_fir_is_empty,
-+    .fd_read = pxa2xx_fir_rx,
-+    .fd_event = pxa2xx_fir_event,
-+};
-+
- static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
-                 qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma,
-                 CharDriverState *chr)
-@@ -2038,10 +2044,9 @@ static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
-                     pxa2xx_fir_writefn, s, DEVICE_NATIVE_ENDIAN);
-     cpu_register_physical_memory(base, 0x1000, iomemtype);
- 
--    if (chr)
--        qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
--                        pxa2xx_fir_rx, pxa2xx_fir_event, s);
--
-+    if (chr) {
-+        qemu_chr_add_handlers(chr, &pxa2xx_handlers, s);
-+    }
-     register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
-                     pxa2xx_fir_load, s);
- 
-diff --git a/hw/serial.c b/hw/serial.c
-index 0ee61dd..d496bcf 100644
---- a/hw/serial.c
-+++ b/hw/serial.c
-@@ -727,6 +727,12 @@ static void serial_reset(void *opaque)
-     qemu_irq_lower(s->irq);
- }
- 
-+static const QemuChrHandlers serial_handlers = {
-+    .fd_can_read = serial_can_receive1,
-+    .fd_read = serial_receive1,
-+    .fd_event = serial_event,
-+};
-+
- static void serial_init_core(SerialState *s)
- {
-     if (!s->chr) {
-@@ -741,8 +747,7 @@ static void serial_init_core(SerialState *s)
- 
-     qemu_register_reset(serial_reset, s);
- 
--    qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
--                          serial_event, s);
-+    qemu_chr_add_handlers(s->chr, &serial_handlers, s);
- }
- 
- /* Change the main reference oscillator frequency. */
-diff --git a/hw/sh_serial.c b/hw/sh_serial.c
-index 191f4a6..8b6460d 100644
---- a/hw/sh_serial.c
-+++ b/hw/sh_serial.c
-@@ -350,6 +350,12 @@ static CPUWriteMemoryFunc * const sh_serial_writefn[] = {
-     &sh_serial_write,
- };
- 
-+static const QemuChrHandlers sh_serial_handlers = {
-+    .fd_can_read = sh_serial_can_receive1,
-+    .fd_read = sh_serial_receive1,
-+    .fd_event = sh_serial_event,
-+};
-+
- void sh_serial_init (target_phys_addr_t base, int feat,
- 		     uint32_t freq, CharDriverState *chr,
- 		     qemu_irq eri_source,
-@@ -389,9 +395,9 @@ void sh_serial_init (target_phys_addr_t base, int feat,
- 
-     s->chr = chr;
- 
--    if (chr)
--        qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
--			      sh_serial_event, s);
-+    if (chr) {
-+        qemu_chr_add_handlers(chr, &sh_serial_handlers, s);
-+    }
- 
-     s->eri = eri_source;
-     s->rxi = rxi_source;
-diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
-index 6fc0105..5968d85 100644
---- a/hw/spapr_vty.c
-+++ b/hw/spapr_vty.c
-@@ -54,12 +54,16 @@ void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
-     qemu_chr_write(dev->chardev, buf, len);
- }
- 
-+static const QemuChrHandlers vty_handlers = {
-+    .fd_can_read = vty_can_receive,
-+    .fd_read = vty_receive,
-+};
-+
- static int spapr_vty_init(VIOsPAPRDevice *sdev)
- {
-     VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
- 
--    qemu_chr_add_handlers(dev->chardev, vty_can_receive,
--                          vty_receive, NULL, dev);
-+    qemu_chr_add_handlers(dev->chardev, vty_handlers, dev);
- 
-     return 0;
- }
-diff --git a/hw/strongarm.c b/hw/strongarm.c
-index 0e03d61..c2dce95 100644
---- a/hw/strongarm.c
-+++ b/hw/strongarm.c
-@@ -1188,6 +1188,12 @@ static CPUWriteMemoryFunc * const strongarm_uart_writefn[] = {
-     strongarm_uart_write,
- };
- 
-+static const QemuChrHandlers strongarm_uart_handlers = {
-+    .fd_can_read = strongarm_uart_can_receive,
-+    .fd_read = strongarm_uart_receive,
-+    .fd_event = strongarm_uart_event,
-+};
-+
- static int strongarm_uart_init(SysBusDevice *dev)
- {
-     StrongARMUARTState *s = FROM_SYSBUS(StrongARMUARTState, dev);
-@@ -1202,11 +1208,7 @@ static int strongarm_uart_init(SysBusDevice *dev)
-     s->tx_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_tx, s);
- 
-     if (s->chr) {
--        qemu_chr_add_handlers(s->chr,
--                        strongarm_uart_can_receive,
--                        strongarm_uart_receive,
--                        strongarm_uart_event,
--                        s);
-+        qemu_chr_add_handlers(s->chr, &strongarm_uart_handlers, s);
-     }
- 
-     return 0;
-diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
-index 2ef7175..ac68022 100644
---- a/hw/syborg_serial.c
-+++ b/hw/syborg_serial.c
-@@ -292,6 +292,12 @@ static const VMStateDescription vmstate_syborg_serial = {
-     }
- };
- 
-+static const QemuChrHandlers syborg_serial_handlers = {
-+    .fd_can_read = syborg_serial_can_receive,
-+    .fd_read = syborg_serial_receive,
-+    .fd_event = syborg_serial_event,
-+};
-+
- static int syborg_serial_init(SysBusDevice *dev)
- {
-     SyborgSerialState *s = FROM_SYSBUS(SyborgSerialState, dev);
-@@ -304,8 +310,7 @@ static int syborg_serial_init(SysBusDevice *dev)
-     sysbus_init_mmio(dev, 0x1000, iomemtype);
-     s->chr = qdev_init_chardev(&dev->qdev);
-     if (s->chr) {
--        qemu_chr_add_handlers(s->chr, syborg_serial_can_receive,
--                              syborg_serial_receive, syborg_serial_event, s);
-+        qemu_chr_add_handlers(s->chr, &syborg_serial_handlers, s);
-     }
-     if (s->fifo_size <= 0) {
-         fprintf(stderr, "syborg_serial: fifo too small\n");
-diff --git a/hw/usb-serial.c b/hw/usb-serial.c
-index 59cb0fb..bebd900 100644
---- a/hw/usb-serial.c
-+++ b/hw/usb-serial.c
-@@ -476,6 +476,12 @@ static void usb_serial_event(void *opaque, int event)
-     }
- }
- 
-+static const QemuChrHandlers usb_serial_handlers = {
-+    .fd_can_read = usb_serial_can_read,
-+    .fd_read = usb_serial_read,
-+    .fd_event = usb_serial_event,
-+};
-+
- static int usb_serial_initfn(USBDevice *dev)
- {
-     USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
-@@ -487,8 +493,7 @@ static int usb_serial_initfn(USBDevice *dev)
-         return -1;
-     }
- 
--    qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
--                          usb_serial_event, s);
-+    qemu_chr_add_handlers(s->cs, &usb_serial_handlers, s);
-     usb_serial_handle_reset(dev);
-     return 0;
- }
-diff --git a/hw/virtio-console.c b/hw/virtio-console.c
-index b076331..147a467 100644
---- a/hw/virtio-console.c
-+++ b/hw/virtio-console.c
-@@ -74,6 +74,12 @@ static void chr_event(void *opaque, int event)
-     }
- }
- 
-+static const QemuChrHandlers chr_handlers = {
-+    .fd_can_read = chr_can_read,
-+    .fd_read = chr_read,
-+    .fd_event = chr_event,
-+};
-+
- static int virtconsole_initfn(VirtIOSerialPort *port)
- {
-     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
-@@ -86,8 +92,7 @@ static int virtconsole_initfn(VirtIOSerialPort *port)
-     }
- 
-     if (vcon->chr) {
--        qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
--                              vcon);
-+        qemu_chr_add_handlers(vcon->chr, &chr_handlers, vcon);
-         info->have_data = flush_buf;
-         info->guest_open = guest_open;
-         info->guest_close = guest_close;
-@@ -105,7 +110,7 @@ static int virtconsole_exitfn(VirtIOSerialPort *port)
- 	 * Instead of closing the chardev, free it so it can be used
- 	 * for other purposes.
- 	 */
--	qemu_chr_add_handlers(vcon->chr, NULL, NULL, NULL, NULL);
-+	qemu_chr_add_handlers(vcon->chr, NULL, NULL);
-     }
- 
-     return 0;
-diff --git a/hw/xen_console.c b/hw/xen_console.c
-index c6c8163..4c39310 100644
---- a/hw/xen_console.c
-+++ b/hw/xen_console.c
-@@ -201,6 +201,11 @@ static int con_init(struct XenDevice *xendev)
-     return 0;
- }
- 
-+static const QemuChrHandlers xencons_handlers = {
-+    .fd_can_read = xencons_can_receive,
-+    .fd_read = xencons_receive,
-+};
-+
- static int con_connect(struct XenDevice *xendev)
- {
-     struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
-@@ -221,9 +226,9 @@ static int con_connect(struct XenDevice *xendev)
- 	return -1;
- 
-     xen_be_bind_evtchn(&con->xendev);
--    if (con->chr)
--        qemu_chr_add_handlers(con->chr, xencons_can_receive, xencons_receive,
--                              NULL, con);
-+    if (con->chr) {
-+        qemu_chr_add_handlers(con->chr, &xencons_handlers, con);
-+    }
- 
-     xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
- 		  con->ring_ref,
-@@ -237,8 +242,9 @@ static void con_disconnect(struct XenDevice *xendev)
- {
-     struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
- 
--    if (con->chr)
--        qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
-+    if (con->chr) {
-+        qemu_chr_add_handlers(con->chr, NULL, NULL);
-+    }
-     xen_be_unbind_evtchn(&con->xendev);
- 
-     if (con->sring) {
-diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
-index 9b94e98..1845577 100644
---- a/hw/xilinx_uartlite.c
-+++ b/hw/xilinx_uartlite.c
-@@ -193,6 +193,12 @@ static void uart_event(void *opaque, int event)
- 
- }
- 
-+static const QemuChrHandlers uart_handlers = {
-+    .fd_can_read = uart_can_rx,
-+    .fd_read = uart_rx,
-+    .fd_event = uart_event,
-+};
-+
- static int xilinx_uartlite_init(SysBusDevice *dev)
- {
-     struct xlx_uartlite *s = FROM_SYSBUS(typeof (*s), dev);
-@@ -206,8 +212,9 @@ static int xilinx_uartlite_init(SysBusDevice *dev)
-     sysbus_init_mmio(dev, R_MAX * 4, uart_regs);
- 
-     s->chr = qdev_init_chardev(&dev->qdev);
--    if (s->chr)
--        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
-+    if (s->chr) {
-+        qemu_chr_add_handlers(s->chr, &uart_handlers, s);
-+    }
-     return 0;
- }
- 
-diff --git a/monitor.c b/monitor.c
-index a6388a9..5e7ce62 100644
---- a/monitor.c
-+++ b/monitor.c
-@@ -5238,6 +5238,18 @@ static void monitor_event(void *opaque, int event)
-  * End:
-  */
- 
-+static const QemuChrHandlers monitor_handlers = {
-+    .fd_can_read = monitor_can_read,
-+    .fd_read = monitor_read,
-+    .fd_event = monitor_event,
-+};
-+
-+static const QemuChrHandlers monitor_control_handlers = {
-+    .fd_can_read = monitor_can_read,
-+    .fd_read = monitor_control_read,
-+    .fd_event = monitor_control_event,
-+};
-+
- void monitor_init(CharDriverState *chr, int flags)
- {
-     static int is_first_init = 1;
-@@ -5260,12 +5272,10 @@ void monitor_init(CharDriverState *chr, int flags)
-     if (monitor_ctrl_mode(mon)) {
-         mon->mc = qemu_mallocz(sizeof(MonitorControl));
-         /* Control mode requires special handlers */
--        qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read,
--                              monitor_control_event, mon);
-+        qemu_chr_add_handlers(chr, &monitor_control_handlers, mon);
-         qemu_chr_set_echo(chr, true);
-     } else {
--        qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
--                              monitor_event, mon);
-+        qemu_chr_add_handlers(chr, &monitor_handlers, mon);
-     }
- 
-     QLIST_INSERT_HEAD(&mon_list, mon, entry);
-diff --git a/net/slirp.c b/net/slirp.c
-index e057a14..6eb0c51 100644
---- a/net/slirp.c
-+++ b/net/slirp.c
-@@ -576,6 +576,11 @@ static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
-     slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size);
- }
- 
-+static const QemuChrHandlers guestfwd_handlers = {
-+    .fd_can_read = guestfwd_can_read,
-+    .fd_read = guestfwd_read,
-+};
-+
- static int slirp_guestfwd(SlirpState *s, const char *config_str,
-                           int legacy_format)
- {
-@@ -632,8 +637,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
-     fwd->port = port;
-     fwd->slirp = s->slirp;
- 
--    qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
--                          NULL, fwd);
-+    qemu_chr_add_handlers(fwd->hd, &guestfwd_handlers, fwd);
-     return 0;
- 
-  fail_syntax:
-diff --git a/qemu-char.c b/qemu-char.c
-index 75efa60..ee763d5 100644
---- a/qemu-char.c
-+++ b/qemu-char.c
-@@ -190,19 +190,26 @@ void qemu_chr_send_event(CharDriverState *s, int event)
-         s->chr_send_event(s, event);
- }
- 
-+static const QemuChrHandlers null_handlers = {
-+    /* All handlers are initialised to NULL */
-+};
-+
- void qemu_chr_add_handlers(CharDriverState *s,
--                           IOCanReadHandler *fd_can_read,
--                           IOReadHandler *fd_read,
--                           IOEventHandler *fd_event,
--                           void *opaque)
-+                           const QemuChrHandlers *handlers, void *opaque)
- {
--    if (!opaque && !fd_can_read && !fd_read && !fd_event) {
-+    if (!s) {
-+        return;
-+    }
-+    if (!opaque && !handlers) {
-         /* chr driver being released. */
-         ++s->avail_connections;
-     }
--    s->chr_can_read = fd_can_read;
--    s->chr_read = fd_read;
--    s->chr_event = fd_event;
-+    if (!handlers) {
-+        handlers = &null_handlers;
-+    }
-+    s->chr_can_read = handlers->fd_can_read;
-+    s->chr_read = handlers->fd_read;
-+    s->chr_event = handlers->fd_event;
-     s->handler_opaque = opaque;
-     if (s->chr_update_read_handler)
-         s->chr_update_read_handler(s);
-@@ -440,6 +447,12 @@ static void mux_chr_event(void *opaque, int event)
-         mux_chr_send_event(d, i, event);
- }
- 
-+static const QemuChrHandlers mux_chr_handlers = {
-+    .fd_can_read = mux_chr_can_read,
-+    .fd_read = mux_chr_read,
-+    .fd_event = mux_chr_event,
-+};
-+
- static void mux_chr_update_read_handler(CharDriverState *chr)
- {
-     MuxDriver *d = chr->opaque;
-@@ -454,8 +467,7 @@ static void mux_chr_update_read_handler(CharDriverState *chr)
-     d->chr_event[d->mux_cnt] = chr->chr_event;
-     /* Fix up the real driver with mux routines */
-     if (d->mux_cnt == 0) {
--        qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read,
--                              mux_chr_event, chr);
-+        qemu_chr_add_handlers(d->drv, &mux_chr_handlers, chr);
-     }
-     if (d->focus != -1) {
-         mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
-diff --git a/qemu-char.h b/qemu-char.h
-index 892c6da..c8e3f2b 100644
---- a/qemu-char.h
-+++ b/qemu-char.h
-@@ -1,6 +1,7 @@
- #ifndef QEMU_CHAR_H
- #define QEMU_CHAR_H
- 
-+#include <stdbool.h>
- #include "qemu-common.h"
- #include "qemu-queue.h"
- #include "qemu-option.h"
-@@ -76,6 +77,13 @@ struct CharDriverState {
-     QTAILQ_ENTRY(CharDriverState) next;
- };
- 
-+typedef struct QemuChrHandlers {
-+    IOCanReadHandler *fd_can_read;
-+    IOReadHandler *fd_read;
-+    IOHandler *fd_write_unblocked;
-+    IOEventHandler *fd_event;
-+} QemuChrHandlers;
-+
- QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
- CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
-                                     void (*init)(struct CharDriverState *s));
-@@ -88,10 +96,7 @@ void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
-     GCC_FMT_ATTR(2, 3);
- int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
- void qemu_chr_send_event(CharDriverState *s, int event);
--void qemu_chr_add_handlers(CharDriverState *s,
--                           IOCanReadHandler *fd_can_read,
--                           IOReadHandler *fd_read,
--                           IOEventHandler *fd_event,
-+void qemu_chr_add_handlers(CharDriverState *s, const QemuChrHandlers *handlers,
-                            void *opaque);
- int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg);
- void qemu_chr_generic_open(CharDriverState *s);
-diff --git a/usb-redir.c b/usb-redir.c
-index e212993..e2b5a2c 100644
---- a/usb-redir.c
-+++ b/usb-redir.c
-@@ -782,6 +782,12 @@ static void usbredir_chardev_event(void *opaque, int event)
-     }
- }
- 
-+static const QemuChrHandlers usbredir_chr_handlers = {
-+    .fd_can_read = usbredir_chardev_can_read,
-+    .fd_read = usbredir_chardev_read,
-+    .fd_event = usbredir_chardev_event,
-+};
-+
- /*
-  * init + destroy
-  */
-@@ -807,8 +813,7 @@ static int usbredir_initfn(USBDevice *udev)
-     /* We'll do the attach once we receive the speed from the usb-host */
-     udev->auto_attach = 0;
- 
--    qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
--                          usbredir_chardev_read, usbredir_chardev_event, dev);
-+    qemu_chr_add_handlers(dev->cs, &usbredir_chr_handlers, dev);
- 
-     return 0;
- }
--- 
-1.7.5.1
-
diff --git a/0027-iohandlers-Add-enable-disable_write_fd_handler-funct.patch b/0027-iohandlers-Add-enable-disable_write_fd_handler-funct.patch
deleted file mode 100644
index 9c6620a..0000000
--- a/0027-iohandlers-Add-enable-disable_write_fd_handler-funct.patch
+++ /dev/null
@@ -1,77 +0,0 @@
-From 328ddb228ed9e5509b8418b1f34de6d6aff83d62 Mon Sep 17 00:00:00 2001
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 20:32:58 +0100
-Subject: [PATCH 27/35] iohandlers: Add enable/disable_write_fd_handler()
- functions
-
-These will be used to provide a cleaner API for the nonblocking case.
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
----
- iohandler.c |   35 +++++++++++++++++++++++++++++++++++
- qemu-char.h |    3 +++
- 2 files changed, 38 insertions(+), 0 deletions(-)
-
-diff --git a/iohandler.c b/iohandler.c
-index 2b82421..8e6628b 100644
---- a/iohandler.c
-+++ b/iohandler.c
-@@ -44,6 +44,41 @@ typedef struct IOHandlerRecord {
- static QLIST_HEAD(, IOHandlerRecord) io_handlers =
-     QLIST_HEAD_INITIALIZER(io_handlers);
- 
-+static IOHandlerRecord *find_iohandler(int fd)
-+{
-+    IOHandlerRecord *ioh;
-+
-+    QLIST_FOREACH(ioh, &io_handlers, next) {
-+        if (ioh->fd == fd) {
-+            return ioh;
-+        }
-+    }
-+    return NULL;
-+}
-+
-+void enable_write_fd_handler(int fd, IOHandler *fd_write)
-+{
-+    IOHandlerRecord *ioh;
-+
-+    ioh = find_iohandler(fd);
-+    if (!ioh) {
-+        return;
-+    }
-+
-+    ioh->fd_write = fd_write;
-+}
-+
-+void disable_write_fd_handler(int fd)
-+{
-+    IOHandlerRecord *ioh;
-+
-+    ioh = find_iohandler(fd);
-+    if (!ioh) {
-+        return;
-+    }
-+
-+    ioh->fd_write = NULL;
-+}
- 
- /* XXX: fd_read_poll should be suppressed, but an API change is
-    necessary in the character devices to suppress fd_can_read(). */
-diff --git a/qemu-char.h b/qemu-char.h
-index c8e3f2b..7d5dc6c 100644
---- a/qemu-char.h
-+++ b/qemu-char.h
-@@ -121,6 +121,9 @@ size_t qemu_chr_mem_osize(const CharDriverState *chr);
- 
- /* async I/O support */
- 
-+void enable_write_fd_handler(int fd, IOHandler *fd_write);
-+void disable_write_fd_handler(int fd);
-+
- int qemu_set_fd_handler2(int fd,
-                          IOCanReadHandler *fd_read_poll,
-                          IOHandler *fd_read,
--- 
-1.7.5.1
-
diff --git a/0028-char-Add-framework-for-a-write-unblocked-callback.patch b/0028-char-Add-framework-for-a-write-unblocked-callback.patch
deleted file mode 100644
index dc32f9b..0000000
--- a/0028-char-Add-framework-for-a-write-unblocked-callback.patch
+++ /dev/null
@@ -1,61 +0,0 @@
-From 59ff8a6457e82aadad7529602da68406de374a33 Mon Sep 17 00:00:00 2001
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 21:41:42 +0100
-Subject: [PATCH 28/35] char: Add framework for a 'write unblocked' callback
-
-The char layer can let users know that the driver will block on further
-input.  For users interested in not blocking, they can assign a function
-pointer that will be called back when the driver becomes writable.  This
-patch just adds the function pointers to the CharDriverState structure,
-future patches will enable the nonblocking and callback functionality.
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
----
- qemu-char.c |    3 +++
- qemu-char.h |    4 ++++
- 2 files changed, 7 insertions(+), 0 deletions(-)
-
-diff --git a/qemu-char.c b/qemu-char.c
-index ee763d5..830f0c3 100644
---- a/qemu-char.c
-+++ b/qemu-char.c
-@@ -209,11 +209,14 @@ void qemu_chr_add_handlers(CharDriverState *s,
-     }
-     s->chr_can_read = handlers->fd_can_read;
-     s->chr_read = handlers->fd_read;
-+    s->chr_write_unblocked = handlers->fd_write_unblocked;
-     s->chr_event = handlers->fd_event;
-     s->handler_opaque = opaque;
-     if (s->chr_update_read_handler)
-         s->chr_update_read_handler(s);
- 
-+    s->write_blocked = false;
-+
-     /* We're connecting to an already opened device, so let's make sure we
-        also get the open event */
-     if (s->opened) {
-diff --git a/qemu-char.h b/qemu-char.h
-index 7d5dc6c..e942bdf 100644
---- a/qemu-char.h
-+++ b/qemu-char.h
-@@ -61,6 +61,9 @@ struct CharDriverState {
-     IOEventHandler *chr_event;
-     IOCanReadHandler *chr_can_read;
-     IOReadHandler *chr_read;
-+    IOHandler *chr_write_unblocked;
-+    void (*chr_enable_write_fd_handler)(struct CharDriverState *chr);
-+    void (*chr_disable_write_fd_handler)(struct CharDriverState *chr);
-     void *handler_opaque;
-     void (*chr_send_event)(struct CharDriverState *chr, int event);
-     void (*chr_close)(struct CharDriverState *chr);
-@@ -74,6 +77,7 @@ struct CharDriverState {
-     char *filename;
-     int opened;
-     int avail_connections;
-+    bool write_blocked; /* Are we in a blocked state? */
-     QTAILQ_ENTRY(CharDriverState) next;
- };
- 
--- 
-1.7.5.1
-
diff --git a/0029-char-Update-send_all-to-handle-nonblocking-chardev-w.patch b/0029-char-Update-send_all-to-handle-nonblocking-chardev-w.patch
deleted file mode 100644
index db4edba..0000000
--- a/0029-char-Update-send_all-to-handle-nonblocking-chardev-w.patch
+++ /dev/null
@@ -1,199 +0,0 @@
-From 4178a8240badad028ffd13482352510ad6a050e4 Mon Sep 17 00:00:00 2001
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 22:00:27 +0100
-Subject: [PATCH 29/35] char: Update send_all() to handle nonblocking chardev
- write requests
-
-The send_all function is modified to return to the caller in case the
-driver cannot handle any more data.  It returns -EAGAIN or
-WSAEWOULDBLOCK on non-Windows and Windows platforms respectively.  This
-is only done when the caller sets a callback function handler indicating
-it's not interested in blocking till the driver has written out all the
-data.
-
-Currently there's no driver or caller that supports this.  Future
-commits will add such capability.
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
----
- net/socket.c  |    4 +-
- qemu-char.c   |   80 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
- qemu_socket.h |    2 +-
- 3 files changed, 77 insertions(+), 9 deletions(-)
-
-diff --git a/net/socket.c b/net/socket.c
-index bc1bf58..a40687a 100644
---- a/net/socket.c
-+++ b/net/socket.c
-@@ -56,8 +56,8 @@ static ssize_t net_socket_receive(VLANClientState *nc, const uint8_t *buf, size_
-     uint32_t len;
-     len = htonl(size);
- 
--    send_all(s->fd, (const uint8_t *)&len, sizeof(len));
--    return send_all(s->fd, buf, size);
-+    send_all(NULL, s->fd, (const uint8_t *)&len, sizeof(len));
-+    return send_all(NULL, s->fd, buf, size);
- }
- 
- static ssize_t net_socket_receive_dgram(VLANClientState *nc, const uint8_t *buf, size_t size)
-diff --git a/qemu-char.c b/qemu-char.c
-index 830f0c3..88b22c3 100644
---- a/qemu-char.c
-+++ b/qemu-char.c
-@@ -506,7 +506,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
- 
- 
- #ifdef _WIN32
--int send_all(int fd, const void *buf, int len1)
-+static int do_send(int fd, const void *buf, int len1, bool nonblock)
- {
-     int ret, len;
- 
-@@ -514,9 +514,14 @@ int send_all(int fd, const void *buf, int len1)
-     while (len > 0) {
-         ret = send(fd, buf, len, 0);
-         if (ret < 0) {
-+            if (nonblock && len1 - len) {
-+                return len1 - len;
-+            }
-             errno = WSAGetLastError();
-             if (errno != WSAEWOULDBLOCK) {
-                 return -1;
-+            } else if (errno == WSAEWOULDBLOCK && nonblock) {
-+                return WSAEWOULDBLOCK;
-             }
-         } else if (ret == 0) {
-             break;
-@@ -530,7 +535,7 @@ int send_all(int fd, const void *buf, int len1)
- 
- #else
- 
--int send_all(int fd, const void *_buf, int len1)
-+static int do_send(int fd, const void *_buf, int len1, bool nonblock)
- {
-     int ret, len;
-     const uint8_t *buf = _buf;
-@@ -539,8 +544,15 @@ int send_all(int fd, const void *_buf, int len1)
-     while (len > 0) {
-         ret = write(fd, buf, len);
-         if (ret < 0) {
--            if (errno != EINTR && errno != EAGAIN)
-+            if (nonblock && len1 - len) {
-+                return len1 - len;
-+            }
-+            if (errno == EAGAIN && nonblock) {
-+                return -EAGAIN;
-+            }
-+            if (errno != EINTR && errno != EAGAIN) {
-                 return -1;
-+            }
-         } else if (ret == 0) {
-             break;
-         } else {
-@@ -552,6 +564,55 @@ int send_all(int fd, const void *_buf, int len1)
- }
- #endif /* !_WIN32 */
- 
-+int send_all(CharDriverState *chr, int fd, const void *_buf, int len1)
-+{
-+    int ret, eagain_errno;
-+    bool nonblock;
-+
-+    if (chr && chr->write_blocked) {
-+        /*
-+         * We don't handle this situation: the caller should not send
-+         * us data while we're blocked.
-+         *
-+         * We could buffer this data here but that'll only encourage
-+         * bad behaviour on part of the callers.
-+         *
-+         * Also, the data already in fd's buffers isn't easily
-+         * migratable.  If we want full migration support, all the
-+         * data landing here needs to be buffered and on migration,
-+         * anything that's unsent needs to be transferred to the
-+         * dest. machine (which again isn't a very good way of solving
-+         * the problem, as the src may become writable just during
-+         * migration and the reader could receive some data twice,
-+         * essentially corrupting the data).
-+         */
-+        abort();
-+    }
-+
-+    nonblock = false;
-+    /*
-+     * Ensure the char backend is able to receive and handle the
-+     * 'write unblocked' event before we turn on nonblock support.
-+     */
-+    if (chr && chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) {
-+        nonblock = true;
-+    }
-+    ret = do_send(fd, _buf, len1, nonblock);
-+
-+#ifdef _WIN32
-+    eagain_errno = WSAEWOULDBLOCK;
-+#else
-+    eagain_errno = -EAGAIN;
-+#endif
-+
-+    if (nonblock && (ret == eagain_errno || (ret >= 0 && ret < len1))) {
-+        /* Update fd handler to wake up when chr becomes writable */
-+        chr->chr_enable_write_fd_handler(chr);
-+        chr->write_blocked = true;
-+    }
-+    return ret;
-+}
-+
- #ifndef _WIN32
- 
- typedef struct {
-@@ -565,7 +626,7 @@ static int stdio_nb_clients = 0;
- static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
- {
-     FDCharDriver *s = chr->opaque;
--    return send_all(s->fd_out, buf, len);
-+    return send_all(chr, s->fd_out, buf, len);
- }
- 
- static int fd_chr_read_poll(void *opaque)
-@@ -881,7 +942,7 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
-         pty_chr_update_read_handler(chr);
-         return 0;
-     }
--    return send_all(s->fd, buf, len);
-+    return send_all(chr, s->fd, buf, len);
- }
- 
- static int pty_chr_read_poll(void *opaque)
-@@ -1950,8 +2011,15 @@ static void tcp_closed(void *opaque)
- static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
- {
-     TCPCharDriver *s = chr->opaque;
-+
-     if (s->connected) {
--        return send_all(s->fd, buf, len);
-+        int ret;
-+
-+        ret = send_all(chr, s->fd, buf, len);
-+        if (ret == -1 && errno == EPIPE) {
-+            tcp_closed(chr);
-+        }
-+        return ret;
-     } else {
-         /* XXX: indicate an error ? */
-         return len;
-diff --git a/qemu_socket.h b/qemu_socket.h
-index 180e4db..6f453e5 100644
---- a/qemu_socket.h
-+++ b/qemu_socket.h
-@@ -36,7 +36,7 @@ int inet_aton(const char *cp, struct in_addr *ia);
- int qemu_socket(int domain, int type, int protocol);
- int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
- void socket_set_nonblock(int fd);
--int send_all(int fd, const void *buf, int len1);
-+int send_all(CharDriverState *chr, int fd, const void *buf, int len1);
- 
- /* New, ipv6-ready socket helper functions, see qemu-sockets.c */
- int inet_listen_opts(QemuOpts *opts, int port_offset);
--- 
-1.7.5.1
-
diff --git a/0030-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch b/0030-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch
deleted file mode 100644
index 0594e32..0000000
--- a/0030-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch
+++ /dev/null
@@ -1,81 +0,0 @@
-From 56cbfb533c04cde3a55c1345ea0f9097b1ab13fa Mon Sep 17 00:00:00 2001
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 22:02:47 +0100
-Subject: [PATCH 30/35] char: Equip the unix/tcp backend to handle nonblocking
- writes#
-
-Now that the infrastructure is in place to return -EAGAIN to callers,
-individual char drivers can set their update_fd_handlers() function to
-set or remove an fd's write handler.  This handler checks if the driver
-became writable.
-
-A generic callback routine is used for unblocking writes and letting
-users of chardevs know that a driver became writable again.
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
----
- qemu-char.c |   34 ++++++++++++++++++++++++++++++++++
- 1 files changed, 34 insertions(+), 0 deletions(-)
-
-diff --git a/qemu-char.c b/qemu-char.c
-index 88b22c3..e9d7f0a 100644
---- a/qemu-char.c
-+++ b/qemu-char.c
-@@ -106,6 +106,19 @@
- static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
-     QTAILQ_HEAD_INITIALIZER(chardevs);
- 
-+/*
-+ * Generic routine that gets called when chardev becomes writable.
-+ * Lets chardev user know it's OK to send more data.
-+ */
-+static void char_write_unblocked(void *opaque)
-+{
-+    CharDriverState *chr = opaque;
-+
-+    chr->write_blocked = false;
-+    chr->chr_disable_write_fd_handler(chr);
-+    chr->chr_write_unblocked(chr->handler_opaque);
-+}
-+
- static void qemu_chr_event(CharDriverState *s, int event)
- {
-     /* Keep track if the char device is open */
-@@ -2268,6 +2281,25 @@ static void tcp_chr_close(CharDriverState *chr)
-     qemu_chr_event(chr, CHR_EVENT_CLOSED);
- }
- 
-+static void tcp_enable_write_fd_handler(CharDriverState *chr)
-+{
-+    TCPCharDriver *s = chr->opaque;
-+
-+    /*
-+     * This function is called only after tcp_chr_connect() is called
-+     * (either in 'server' mode or client mode.  So we're sure of
-+     * s->fd being initialised.
-+     */
-+    enable_write_fd_handler(s->fd, char_write_unblocked);
-+}
-+
-+static void tcp_disable_write_fd_handler(CharDriverState *chr)
-+{
-+    TCPCharDriver *s = chr->opaque;
-+
-+    disable_write_fd_handler(s->fd);
-+}
-+
- static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
- {
-     CharDriverState *chr = NULL;
-@@ -2320,6 +2352,8 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
-     chr->chr_write = tcp_chr_write;
-     chr->chr_close = tcp_chr_close;
-     chr->get_msgfd = tcp_get_msgfd;
-+    chr->chr_enable_write_fd_handler = tcp_enable_write_fd_handler;
-+    chr->chr_disable_write_fd_handler = tcp_disable_write_fd_handler;
- 
-     if (is_listen) {
-         s->listen_fd = fd;
--- 
-1.7.5.1
-
diff --git a/0031-char-Throttle-when-host-connection-is-down.patch b/0031-char-Throttle-when-host-connection-is-down.patch
deleted file mode 100644
index a60c0e7..0000000
--- a/0031-char-Throttle-when-host-connection-is-down.patch
+++ /dev/null
@@ -1,56 +0,0 @@
-From 00cf9482be18cdacda0ae9b207b84a7e86ca1d11 Mon Sep 17 00:00:00 2001
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 22:05:10 +0100
-Subject: [PATCH 31/35] char: Throttle when host connection is down#
-
-When the host-side connection goes down, throttle the virtio-serial bus
-and later unthrottle when a connection gets established.  This helps
-prevent any lost IO (guest->host) while the host connection was down.
-
-Bugzilla: 621484
-
-This commit actually helps the bug mentioned above as no writes will now
-get lost because of the throttling done here.  With just the patches
-sent earlier for that bug, one write will end up getting lost in the
-worst case (host d/c, guest write, host connect).
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
----
- qemu-char.c |   14 ++++++++++++++
- 1 files changed, 14 insertions(+), 0 deletions(-)
-
-diff --git a/qemu-char.c b/qemu-char.c
-index e9d7f0a..77ab1ed 100644
---- a/qemu-char.c
-+++ b/qemu-char.c
-@@ -140,6 +140,9 @@ static void qemu_chr_generic_open_bh(void *opaque)
- {
-     CharDriverState *s = opaque;
-     qemu_chr_event(s, CHR_EVENT_OPENED);
-+    if (s->write_blocked) {
-+        char_write_unblocked(s);
-+    }
-     qemu_bh_delete(s->bh);
-     s->bh = NULL;
- }
-@@ -2031,6 +2034,17 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
-         ret = send_all(chr, s->fd, buf, len);
-         if (ret == -1 && errno == EPIPE) {
-             tcp_closed(chr);
-+
-+            if (chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) {
-+                /*
-+                 * Since we haven't written out anything, let's say
-+                 * we're throttled.  This will prevent any output from
-+                 * the guest getting lost if host-side chardev goes
-+                 * down.  Unthrottle when we re-connect.
-+                 */
-+                chr->write_blocked = true;
-+                return 0;
-+            }
-         }
-         return ret;
-     } else {
--- 
-1.7.5.1
-
diff --git a/0032-virtio-console-Enable-port-throttling-when-chardev-i.patch b/0032-virtio-console-Enable-port-throttling-when-chardev-i.patch
deleted file mode 100644
index 4d130a8..0000000
--- a/0032-virtio-console-Enable-port-throttling-when-chardev-i.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-From ba203585e61d1fbe6ba45683d958d261678641ad Mon Sep 17 00:00:00 2001
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 22:06:41 +0100
-Subject: [PATCH 32/35] virtio-console: Enable port throttling when chardev is
- slow to consume data
-
-When a chardev indicates it can't accept more data, we tell the
-virtio-serial code to stop sending us any more data till we tell
-otherwise.  This helps in guests continuing to run normally while the vq
-keeps getting full and eventually the guest stops queueing more data.
-As soon as the chardev indicates it can accept more data, start pushing!
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
----
- hw/virtio-console.c |   11 +++++++++++
- 1 files changed, 11 insertions(+), 0 deletions(-)
-
-diff --git a/hw/virtio-console.c b/hw/virtio-console.c
-index 147a467..9286f6e 100644
---- a/hw/virtio-console.c
-+++ b/hw/virtio-console.c
-@@ -19,6 +19,16 @@ typedef struct VirtConsole {
-     CharDriverState *chr;
- } VirtConsole;
- 
-+/*
-+ * Callback function that's called from chardevs when backend becomes
-+ * writable.
-+ */
-+static void chr_write_unblocked(void *opaque)
-+{
-+    VirtConsole *vcon = opaque;
-+
-+    virtio_serial_throttle_port(&vcon->port, false);
-+}
- 
- /* Callback function that's called when the guest sends us data */
- static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
-@@ -78,6 +88,7 @@ static const QemuChrHandlers chr_handlers = {
-     .fd_can_read = chr_can_read,
-     .fd_read = chr_read,
-     .fd_event = chr_event,
-+    .fd_write_unblocked = chr_write_unblocked,
- };
- 
- static int virtconsole_initfn(VirtIOSerialPort *port)
--- 
-1.7.5.1
-
diff --git a/0033-spice-qemu-char.c-add-throttling.patch b/0033-spice-qemu-char.c-add-throttling.patch
deleted file mode 100644
index 0696f81..0000000
--- a/0033-spice-qemu-char.c-add-throttling.patch
+++ /dev/null
@@ -1,133 +0,0 @@
-From 7322ad318ecde8669e68ef1314e97b4553a327fa Mon Sep 17 00:00:00 2001
-From: Alon Levy <alevy@redhat.com>
-Date: Tue, 22 Mar 2011 12:27:59 +0200
-Subject: [PATCH 33/35] spice-qemu-char.c: add throttling
-
-BZ: 672191
-
-upstream: not submitted (explained below)
-
-Adds throttling support to spicevmc chardev. Uses a timer to avoid recursing:
-1. spice-server: reds.c:            read_from_vdi_port
-2. qemu:         spice-qemu-char.c: vmc_read
-3.                                  chr_write_unblocked
-                                (calls virtio_serial_throttle_port(port, false))
-4. qemu:         virtio ...
-5. qemu:         spice-qemu-char.c: spice_chr_write
-6. qemu:         spice-qemu-char.c: wakeup (calls into spice-server)
-7. spice-server: ...
-8. qemu:         spice-qemu-char.c: vmc_read
-
-Instead, in vmc_read if we were throttled and we are just about to return
-all the bytes we will set a timer to be triggered immediately to call
-chr_write_unblocked. Then we return after 2 above, and 3 is called from the
-timer callback. This also means we can later remove some ugly recursion protection
-from spice-server.
-
-The other tricky point in this patch is not returning the leftover chunk twice.
-When we throttle, by definition we have data that spice server didn't consume.
-It is being kept by virtio-serial, and by us. The next vmc_read callback needs
-to not return it, but just do unthrottling. Then virtio will give us the remaining
-chunk as usual in spice_chr_write, and we will pass it to spice server in the
-next vmc_read.
-
-This patch relies on Amit's series to expose throttling to chardev's, which
-was not accepted upstream, and will not be accepted upstream until the mainloop
-is reworked to use glib.
----
- spice-qemu-char.c |   39 +++++++++++++++++++++++++++++++++++----
- 1 files changed, 35 insertions(+), 4 deletions(-)
-
-diff --git a/spice-qemu-char.c b/spice-qemu-char.c
-index 605c241..9348f65 100644
---- a/spice-qemu-char.c
-+++ b/spice-qemu-char.c
-@@ -1,4 +1,6 @@
- #include "config-host.h"
-+#include "qemu-common.h"
-+#include "qemu-timer.h"
- #include "trace.h"
- #include "ui/qemu-spice.h"
- #include <spice.h>
-@@ -25,6 +27,7 @@ typedef struct SpiceCharDriver {
-     uint8_t               *datapos;
-     ssize_t               bufsize, datalen;
-     uint32_t              debug;
-+    QEMUTimer             *unblock_timer;
- } SpiceCharDriver;
- 
- static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
-@@ -50,6 +53,17 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
-     return out;
- }
- 
-+static void spice_chr_unblock(void *opaque)
-+{
-+    SpiceCharDriver *scd = opaque;
-+
-+    if (scd->chr->chr_write_unblocked == NULL) {
-+        dprintf(scd, 1, "%s: backend doesn't support unthrottling.\n", __func__);
-+        return;
-+    }
-+    scd->chr->chr_write_unblocked(scd->chr->handler_opaque);
-+}
-+
- static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
- {
-     SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
-@@ -61,9 +75,16 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
-         scd->datapos += bytes;
-         scd->datalen -= bytes;
-         assert(scd->datalen >= 0);
--        if (scd->datalen == 0) {
--            scd->datapos = 0;
--        }
-+    }
-+    if (scd->datalen == 0 && scd->chr->write_blocked) {
-+        dprintf(scd, 1, "%s: unthrottling (%d)\n", __func__, bytes);
-+        scd->chr->write_blocked = false;
-+        /*
-+         * set a timer instead of calling scd->chr->chr_write_unblocked directly,
-+         * because that will call back into spice_chr_write (see
-+         * virtio-console.c:chr_write_unblocked), which is unwanted.
-+         */
-+        qemu_mod_timer(scd->unblock_timer, 0);
-     }
-     trace_spice_vmc_read(bytes, len);
-     return bytes;
-@@ -106,6 +127,7 @@ static void vmc_unregister_interface(SpiceCharDriver *scd)
- static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
- {
-     SpiceCharDriver *s = chr->opaque;
-+    int read_bytes;
- 
-     dprintf(s, 2, "%s: %d\n", __func__, len);
-     vmc_register_interface(s);
-@@ -118,7 +140,15 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
-     s->datapos = s->buffer;
-     s->datalen = len;
-     spice_server_char_device_wakeup(&s->sin);
--    return len;
-+    read_bytes = len - s->datalen;
-+    if (read_bytes != len) {
-+        dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__,
-+                read_bytes, len, s->bufsize);
-+        s->chr->write_blocked = true;
-+        /* We'll get passed in the unconsumed data with the next call */
-+        s->datalen = 0;
-+    }
-+    return read_bytes;
- }
- 
- static void spice_chr_close(struct CharDriverState *chr)
-@@ -196,6 +226,7 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
-     chr->chr_close = spice_chr_close;
-     chr->chr_guest_open = spice_chr_guest_open;
-     chr->chr_guest_close = spice_chr_guest_close;
-+    s->unblock_timer = qemu_new_timer_ms(vm_clock, spice_chr_unblock, s);
- 
-     qemu_chr_generic_open(chr);
- 
--- 
-1.7.5.1
-
diff --git a/0034-spice-qemu-char.c-remove-intermediate-buffer.patch b/0034-spice-qemu-char.c-remove-intermediate-buffer.patch
deleted file mode 100644
index c2a5c69..0000000
--- a/0034-spice-qemu-char.c-remove-intermediate-buffer.patch
+++ /dev/null
@@ -1,71 +0,0 @@
-From 8b7c5738faa2c7851ecc92182467a564bf7c9109 Mon Sep 17 00:00:00 2001
-From: Alon Levy <alevy@redhat.com>
-Date: Tue, 22 Mar 2011 12:28:00 +0200
-Subject: [PATCH 34/35] spice-qemu-char.c: remove intermediate buffer
-
-BZ: 672191
-upstream: not submitted (explained below)
-
-virtio-serial's buffer is valid when it calls us, and we don't
-access it otherwise: vmc_read is only called in response to wakeup,
-or else we set datalen=0 and throttle. Then vmc_read is called back,
-we return 0 (not accessing the buffer) and set the timer to unthrottle.
-
-Also make datalen int and not ssize_t (to fit spice_chr_write signature).
-
-This relied on the previous patch that introduces throttling, which
-can't go upstream right now as explained in that patch.
----
- spice-qemu-char.c |   18 ++++++------------
- 1 files changed, 6 insertions(+), 12 deletions(-)
-
-diff --git a/spice-qemu-char.c b/spice-qemu-char.c
-index 9348f65..ce75e91 100644
---- a/spice-qemu-char.c
-+++ b/spice-qemu-char.c
-@@ -23,9 +23,8 @@ typedef struct SpiceCharDriver {
-     SpiceCharDeviceInstance     sin;
-     char                  *subtype;
-     bool                  active;
--    uint8_t               *buffer;
--    uint8_t               *datapos;
--    ssize_t               bufsize, datalen;
-+    const uint8_t         *datapos;
-+    int                   datalen;
-     uint32_t              debug;
-     QEMUTimer             *unblock_timer;
- } SpiceCharDriver;
-@@ -69,7 +68,7 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
-     SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
-     int bytes = MIN(len, scd->datalen);
- 
--    dprintf(scd, 2, "%s: %p %d/%d/%zd\n", __func__, scd->datapos, len, bytes, scd->datalen);
-+    dprintf(scd, 2, "%s: %p %d/%d/%d\n", __func__, scd->datapos, len, bytes, scd->datalen);
-     if (bytes > 0) {
-         memcpy(buf, scd->datapos, bytes);
-         scd->datapos += bytes;
-@@ -132,18 +131,13 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
-     dprintf(s, 2, "%s: %d\n", __func__, len);
-     vmc_register_interface(s);
-     assert(s->datalen == 0);
--    if (s->bufsize < len) {
--        s->bufsize = len;
--        s->buffer = qemu_realloc(s->buffer, s->bufsize);
--    }
--    memcpy(s->buffer, buf, len);
--    s->datapos = s->buffer;
-+    s->datapos = buf;
-     s->datalen = len;
-     spice_server_char_device_wakeup(&s->sin);
-     read_bytes = len - s->datalen;
-     if (read_bytes != len) {
--        dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__,
--                read_bytes, len, s->bufsize);
-+        dprintf(s, 1, "%s: throttling: %d < %d\n", __func__,
-+                read_bytes, len);
-         s->chr->write_blocked = true;
-         /* We'll get passed in the unconsumed data with the next call */
-         s->datalen = 0;
--- 
-1.7.5.1
-
diff --git a/0035-usb-redir-Add-flow-control-support.patch b/0035-usb-redir-Add-flow-control-support.patch
deleted file mode 100644
index c03c813..0000000
--- a/0035-usb-redir-Add-flow-control-support.patch
+++ /dev/null
@@ -1,64 +0,0 @@
-From f7f2f55e2a8beb68fc81c1def7a0a4436664ed97 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Tue, 19 Jul 2011 10:56:19 +0200
-Subject: [PATCH 35/35] usb-redir: Add flow control support
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- usb-redir.c |   28 +++++++++++++++++++++++++++-
- 1 files changed, 27 insertions(+), 1 deletions(-)
-
-diff --git a/usb-redir.c b/usb-redir.c
-index e2b5a2c..6932beb 100644
---- a/usb-redir.c
-+++ b/usb-redir.c
-@@ -224,8 +224,22 @@ static int usbredir_read(void *priv, uint8_t *data, int count)
- static int usbredir_write(void *priv, uint8_t *data, int count)
- {
-     USBRedirDevice *dev = priv;
-+    int r;
- 
--    return qemu_chr_write(dev->cs, data, count);
-+    if (dev->cs->write_blocked) {
-+        return 0;
-+    }
-+
-+    r = qemu_chr_write(dev->cs, data, count);
-+
-+    if (r < 0) {
-+        if (dev->cs->write_blocked) {
-+            return 0;
-+        }
-+        return -1;
-+    }
-+
-+    return r;
- }
- 
- /*
-@@ -782,10 +796,22 @@ static void usbredir_chardev_event(void *opaque, int event)
-     }
- }
- 
-+static void usbredir_chardev_write_unblocked(void *opaque)
-+{
-+    USBRedirDevice *dev = opaque;
-+
-+    if (dev->parser == NULL) {
-+        /* usbredir_open_close_bh hasn't handled the open event yet */
-+        return;
-+    }
-+    usbredirparser_do_write(dev->parser);
-+}
-+
- static const QemuChrHandlers usbredir_chr_handlers = {
-     .fd_can_read = usbredir_chardev_can_read,
-     .fd_read = usbredir_chardev_read,
-     .fd_event = usbredir_chardev_event,
-+    .fd_write_unblocked = usbredir_chardev_write_unblocked,
- };
- 
- /*
--- 
-1.7.5.1
-
diff --git a/qemu.spec b/qemu.spec
index f423c2b..0d88168 100644
--- a/qemu.spec
+++ b/qemu.spec
@@ -1,9 +1,9 @@
-%define githead 525e3df
+%define githead 59fadcc
 
 Summary: QEMU is a FAST! processor emulator
 Name: qemu
 Version: 0.15.0
-Release: 0.2.20110718%githead%{?dist}
+Release: 0.2.20110728%githead%{?dist}
 # Epoch because we pushed a qemu-1.0 package
 Epoch: 2
 License: GPLv2+ and LGPLv2+ and BSD
@@ -22,7 +22,7 @@ URL: http://www.qemu.org/
 # Source0: http://downloads.sourceforge.net/sourceforge/kvm/qemu-kvm-%{version}.tar.gz
 # The source for this package was pulled from upstream's git.  Use the
 # following commands to generate the tarball:
-# git archive --format=tar --prefix=qemu-kvm-0.15/ 525e3df | gzip > qemu-kvm-0.15.0-525e3df.tar.gz
+# git archive --format=tar --prefix=qemu-kvm-0.15.0/ 59fadcc | gzip > qemu-kvm-0.15.0-59fadcc.tar.gz
 Source0: qemu-kvm-%{version}-%{githead}.tar.gz
 
 Source1: qemu.init
@@ -40,45 +40,20 @@ Source6: ksmtuned.init
 Source7: ksmtuned
 Source8: ksmtuned.conf
 
-# Sync with: http://www.kraxel.org/cgit/qemu/log/?h=usb.19
-# USB patches waiting to be pulled by upstream
-Patch1:  0001-hw-usb-musb.c-Don-t-misuse-usb_packet_complete.patch
-Patch2:  0002-usb-Add-a-usb_fill_port-helper-function.patch
-Patch3:  0003-usb-Move-initial-call-of-usb_port_location-to-usb_fi.patch
-Patch4:  0004-usb-Add-a-register_companion-USB-bus-op.patch
-Patch5:  0005-usb-Make-port-wakeup-and-complete-ops-take-a-USBPort.patch
-Patch6:  0006-usb-Replace-device_destroy-bus-op-with-a-child_detac.patch
-Patch7:  0007-usb-ehci-drop-unused-num-ports-state-member.patch
-Patch8:  0008-usb-ehci-Connect-Status-bit-is-read-only-don-t-allow.patch
-Patch9:  0009-usb-ehci-cleanup-port-reset-handling.patch
-Patch10: 0010-usb-assert-on-calling-usb_attach-port-NULL-on-a-port.patch
-Patch11: 0011-usb-ehci-Fix-handling-of-PED-and-PEDC-port-status-bi.patch
-Patch12: 0012-usb-ehci-Add-support-for-registering-companion-contr.patch
-Patch13: 0013-usb-uhci-Add-support-for-being-a-companion-controlle.patch
-Patch14: 0014-usb-ohci-Add-support-for-being-a-companion-controlle.patch
-Patch15: 0015-pci-add-ich9-usb-controller-ids.patch
-Patch16: 0016-uhci-add-ich9-controllers.patch
-Patch17: 0017-ehci-fix-port-count.patch
-Patch18: 0018-ehci-add-ich9-controller.patch
-Patch19: 0019-usb-update-documentation.patch
-Patch20: 0020-usb_register_port-do-not-set-port-opaque-and-port-in.patch
-Patch21: 0021-usb-fixup-bluetooth-descriptors.patch
-Patch22: 0022-usb-hub-remove-unused-descriptor-arrays.patch
-Patch23: 0023-usb-ohci-raise-interrupt-on-attach.patch
-# Add usb-redir device, under review upstream
-Patch24: 0024-USB-add-usb-network-redirection-support.patch
 # Amit's flow control patches, waiting to glib conversion before going upstream
-Patch25: 0025-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch
-Patch26: 0026-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch
-Patch27: 0027-iohandlers-Add-enable-disable_write_fd_handler-funct.patch
-Patch28: 0028-char-Add-framework-for-a-write-unblocked-callback.patch
-Patch29: 0029-char-Update-send_all-to-handle-nonblocking-chardev-w.patch
-Patch30: 0030-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch
-Patch31: 0031-char-Throttle-when-host-connection-is-down.patch
-Patch32: 0032-virtio-console-Enable-port-throttling-when-chardev-i.patch
-Patch33: 0033-spice-qemu-char.c-add-throttling.patch
-Patch34: 0034-spice-qemu-char.c-remove-intermediate-buffer.patch
-Patch35: 0035-usb-redir-Add-flow-control-support.patch
+Patch01: 0001-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch
+Patch02: 0002-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch
+Patch03: 0003-iohandlers-Add-enable-disable_write_fd_handler-funct.patch
+Patch04: 0004-char-Add-framework-for-a-write-unblocked-callback.patch
+Patch05: 0005-char-Update-send_all-to-handle-nonblocking-chardev-w.patch
+Patch06: 0006-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch
+Patch07: 0007-char-Throttle-when-host-connection-is-down.patch
+Patch08: 0008-virtio-console-Enable-port-throttling-when-chardev-i.patch
+Patch09: 0009-spice-qemu-char.c-add-throttling.patch
+Patch10: 0010-spice-qemu-char.c-remove-intermediate-buffer.patch
+Patch11: 0011-usb-redir-Add-flow-control-support.patch
+Patch12: 0012-usb-redir-Call-qemu_chr_guest_open-close.patch
+Patch13: 0013-spice-qemu-char-Generate-chardev-open-close-events.patch
 
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 BuildRequires: SDL-devel zlib-devel which texi2html gnutls-devel cyrus-sasl-devel
@@ -252,41 +227,19 @@ such as kvm_stat.
 
 %prep
 %setup -q -n qemu-kvm-%{version}
-%patch1 -p1
-%patch2 -p1
-%patch3 -p1
-%patch4 -p1
-%patch5 -p1
-%patch6 -p1
-%patch7 -p1
-%patch8 -p1
-%patch9 -p1
+%patch01 -p1
+%patch02 -p1
+%patch03 -p1
+%patch04 -p1
+%patch05 -p1
+%patch06 -p1
+%patch07 -p1
+%patch08 -p1
+%patch09 -p1
 %patch10 -p1
 %patch11 -p1
 %patch12 -p1
 %patch13 -p1
-%patch14 -p1
-%patch15 -p1
-%patch16 -p1
-%patch17 -p1
-%patch18 -p1
-%patch19 -p1
-%patch20 -p1
-%patch21 -p1
-%patch22 -p1
-%patch23 -p1
-%patch24 -p1
-%patch25 -p1
-%patch26 -p1
-%patch27 -p1
-%patch28 -p1
-%patch29 -p1
-%patch30 -p1
-%patch31 -p1
-%patch32 -p1
-%patch33 -p1
-%patch34 -p1
-%patch35 -p1
 
 %build
 # By default we build everything, but allow x86 to build a minimal version
@@ -515,6 +468,7 @@ fi
 %{_initddir}/qemu
 %{_bindir}/qemu-i386
 %{_bindir}/qemu-x86_64
+%{_bindir}/qemu-ga
 %if !%{with_x86only}
 %{_bindir}/qemu-alpha
 %{_bindir}/qemu-arm
@@ -596,6 +550,9 @@ fi
 %{_mandir}/man1/qemu-img.1*
 
 %changelog
+* Thu Jul 28 2011 Justin M. Forbes <jforbes@redhat.com> - 2:0.15.0-0.1.2011072859fadcc
+- Update to 0.15.0-rc0 as we prepare for 0.15.0 release
+
 * Tue Jul 19 2011 Hans de Goede <hdegoede@redhat.com> - 2:0.15.0-0.2.20110718525e3df
 - Add support usb redirection over the network, see:
   http://fedoraproject.org/wiki/Features/UsbNetworkRedirection
diff --git a/sources b/sources
index 2826ce6..ff5bb55 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-cbd0d49d1490ca90208609cd158eb080  qemu-kvm-0.15.0-525e3df.tar.gz
+b0d29c5405ec451421d98d335762ff7c  qemu-kvm-0.15.0-59fadcc.tar.gz