From 57e7ceb8b9cc0f09cc12f673930648e872916146 Mon Sep 17 00:00:00 2001
Message-Id: <57e7ceb8b9cc0f09cc12f673930648e872916146.1368111913.git.minovotn@redhat.com>
In-Reply-To: <405603258af5154387bea676be1f904b6713f6ae.1368111913.git.minovotn@redhat.com>
References: <405603258af5154387bea676be1f904b6713f6ae.1368111913.git.minovotn@redhat.com>
From: Amit Shah <amit.shah@redhat.com>
Date: Wed, 24 Apr 2013 08:17:45 +0200
Subject: [PATCH 11/65] Revert "char: Add a QemuChrHandlers struct to
 initialise chardev handlers"

RH-Author: Amit Shah <amit.shah@redhat.com>
Message-id: <482437ae8c311f7fc2c3901d684fd6e24ac52934.1366724981.git.amit.shah@redhat.com>
Patchwork-id: 50789
O-Subject: [RHEL6.5 qemu-kvm PATCH 11/65] Revert "char: Add a QemuChrHandlers struct to initialise chardev handlers"
Bugzilla: 909059
RH-Acked-by: Hans de Goede <hdegoede@redhat.com>
RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com>
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>

This reverts commit 45b991f7d27145deeaabf5cbee5f14d3a0c5dfbd.

Signed-off-by: Amit Shah <amit.shah@redhat.com>

Conflicts:
	hw/virtio-console.c
	monitor.c
	qemu-char.c

* Modified free_chr() in hw/qdev-properties.c to add extra args to
qemu_chr_add_handler()

* Modified qemu_chr_add_handlers() in qemu-char.c to keep code from
later commits 73e6593a and 89aefe25

* Modified hw/debugcon.c and hw/ccid-card-passthrough.c that weren't
included when the orig patch was committed.  Modification is converting
struct to open args

Signed-off-by: Amit Shah <amit.shah@redhat.com>
---
 gdbstub.c               |  9 ++-------
 hw/ccid-card-passthru.c | 10 +++-------
 hw/debugcon.c           |  5 +----
 hw/escc.c               |  9 ++-------
 hw/etraxfs_ser.c        | 13 ++++---------
 hw/mcf_uart.c           |  9 ++-------
 hw/pl011.c              |  9 ++-------
 hw/pxa2xx.c             | 13 ++++---------
 hw/qdev-properties.c    |  2 +-
 hw/serial.c             |  9 ++-------
 hw/sh_serial.c          | 12 +++---------
 hw/syborg_serial.c      |  9 ++-------
 hw/usb-serial.c         |  9 ++-------
 hw/virtio-console.c     | 21 ++-------------------
 hw/xen_console.c        | 16 +++++-----------
 hw/xilinx_uartlite.c    | 11 ++---------
 monitor.c               | 19 ++++---------------
 net/slirp.c             |  8 ++------
 qemu-char.c             | 32 ++++++++++----------------------
 qemu-char.h             | 13 ++++---------
 usb-redir.c             |  9 ++-------
 21 files changed, 61 insertions(+), 186 deletions(-)

Signed-off-by: Michal Novotny <minovotn@redhat.com>
---
 gdbstub.c               |  9 ++-------
 hw/ccid-card-passthru.c | 10 +++-------
 hw/debugcon.c           |  5 +----
 hw/escc.c               |  9 ++-------
 hw/etraxfs_ser.c        | 13 ++++---------
 hw/mcf_uart.c           |  9 ++-------
 hw/pl011.c              |  9 ++-------
 hw/pxa2xx.c             | 13 ++++---------
 hw/qdev-properties.c    |  2 +-
 hw/serial.c             |  9 ++-------
 hw/sh_serial.c          | 12 +++---------
 hw/syborg_serial.c      |  9 ++-------
 hw/usb-serial.c         |  9 ++-------
 hw/virtio-console.c     | 21 ++-------------------
 hw/xen_console.c        | 16 +++++-----------
 hw/xilinx_uartlite.c    | 11 ++---------
 monitor.c               | 19 ++++---------------
 net/slirp.c             |  8 ++------
 qemu-char.c             | 32 ++++++++++----------------------
 qemu-char.h             | 13 ++++---------
 usb-redir.c             |  9 ++-------
 21 files changed, 61 insertions(+), 186 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 7f1e361..68c08d7 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2544,12 +2544,6 @@ 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;
@@ -2579,7 +2573,8 @@ int gdbserver_start(const char *device)
         if (!chr)
             return -1;
 
-        qemu_chr_add_handlers(chr, &gdb_handlers, NULL);
+        qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
+                              gdb_chr_event, NULL);
     }
 
     s = gdbserver_state;
diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
index d713026..5bf75d2 100644
--- a/hw/ccid-card-passthru.c
+++ b/hw/ccid-card-passthru.c
@@ -274,12 +274,6 @@ static const uint8_t *passthru_get_atr(CCIDCardState *base, uint32_t *len)
     return card->atr;
 }
 
-static const QemuChrHandlers ccid_card_vscard_chr_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);
@@ -288,7 +282,9 @@ 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_chr_handlers, card);
+        qemu_chr_add_handlers(card->cs, ccid_card_vscard_can_read,
+                              ccid_card_vscard_read, ccid_card_vscard_event,
+                              card);
         ccid_card_vscard_send_init(card);
     } else {
         error_report("missing chardev");
diff --git a/hw/debugcon.c b/hw/debugcon.c
index 0c1ced0..5ee6821 100644
--- a/hw/debugcon.c
+++ b/hw/debugcon.c
@@ -66,9 +66,6 @@ static uint32_t debugcon_ioport_read(void *opaque, uint32_t addr)
     return s->readback;
 }
 
-static const QemuChrHandlers chr_handlers = {
-};
-
 static void debugcon_init_core(DebugconState *s)
 {
     if (!s->chr) {
@@ -76,7 +73,7 @@ static void debugcon_init_core(DebugconState *s)
         exit(1);
     }
 
-    qemu_chr_add_handlers(s->chr, &chr_handlers, s);
+    qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s);
 }
 
 static int debugcon_isa_initfn(ISADevice *dev)
diff --git a/hw/escc.c b/hw/escc.c
index 0cb1d45..0b20aea 100644
--- a/hw/escc.c
+++ b/hw/escc.c
@@ -890,12 +890,6 @@ 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);
@@ -909,7 +903,8 @@ 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_handlers, &s->chn[i]);
+            qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
+                                  serial_receive1, serial_event, &s->chn[i]);
         }
     }
     s->chn[0].otherchn = &s->chn[1];
diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
index 0c0c485..e1f9615 100644
--- a/hw/etraxfs_ser.c
+++ b/hw/etraxfs_ser.c
@@ -161,12 +161,6 @@ static void serial_event(void *opaque, int event)
 
 }
 
-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);
@@ -180,9 +174,10 @@ static int etraxfs_ser_init(SysBusDevice *dev)
     ser_regs = cpu_register_io_memory(ser_read, ser_write, s);
     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_handlers, s);
-    }
+    if (s->chr)
+        qemu_chr_add_handlers(s->chr,
+                      serial_can_receive, serial_receive,
+                      serial_event, s);
     return 0;
 }
 
diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c
index d2ce5f6..d16bac7 100644
--- a/hw/mcf_uart.c
+++ b/hw/mcf_uart.c
@@ -268,12 +268,6 @@ 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;
@@ -282,7 +276,8 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
     s->chr = chr;
     s->irq = irq;
     if (chr) {
-        qemu_chr_add_handlers(chr, &mcf_uart_handlers, s);
+        qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
+                              mcf_uart_event, s);
     }
     mcf_uart_reset(s);
     return s;
diff --git a/hw/pl011.c b/hw/pl011.c
index 339d4ac..02cf84a 100644
--- a/hw/pl011.c
+++ b/hw/pl011.c
@@ -286,12 +286,6 @@ static int pl011_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-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;
@@ -309,7 +303,8 @@ 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_handlers, s);
+        qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
+                              pl011_event, s);
     }
     register_savevm(&dev->qdev, "pl011_uart", -1, 1, pl011_save, pl011_load, s);
     return 0;
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 3973681..8be207a 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -1992,12 +1992,6 @@ 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, PXA2xxDMAState *dma,
                 CharDriverState *chr)
@@ -2016,9 +2010,10 @@ static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
                     pxa2xx_fir_writefn, s);
     cpu_register_physical_memory(base, 0x1000, iomemtype);
 
-    if (chr) {
-        qemu_chr_add_handlers(chr, &pxa2xx_handlers, s);
-    }
+    if (chr)
+        qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
+                        pxa2xx_fir_rx, pxa2xx_fir_event, s);
+
     register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
                     pxa2xx_fir_load, s);
 
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index b347298..d47b213 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -370,7 +370,7 @@ static void free_chr(DeviceState *dev, Property *prop)
     CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
 
     if (*ptr) {
-        qemu_chr_add_handlers(*ptr, NULL, NULL);
+        qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
     }
 }
 
diff --git a/hw/serial.c b/hw/serial.c
index 8e92f67..3edd6fa 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -718,12 +718,6 @@ 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) {
@@ -738,7 +732,8 @@ static void serial_init_core(SerialState *s)
 
     qemu_register_reset(serial_reset, s);
 
-    qemu_chr_add_handlers(s->chr, &serial_handlers, s);
+    qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
+                          serial_event, s);
 }
 
 /* Change the main reference oscillator frequency. */
diff --git a/hw/sh_serial.c b/hw/sh_serial.c
index a66a57a..2447b91 100644
--- a/hw/sh_serial.c
+++ b/hw/sh_serial.c
@@ -363,12 +363,6 @@ 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,
@@ -407,9 +401,9 @@ void sh_serial_init (target_phys_addr_t base, int feat,
 
     s->chr = chr;
 
-    if (chr) {
-        qemu_chr_add_handlers(chr, &sh_serial_handlers, s);
-    }
+    if (chr)
+        qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
+			      sh_serial_event, s);
 
     s->eri = eri_source;
     s->rxi = rxi_source;
diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
index febcd15..8c42956 100644
--- a/hw/syborg_serial.c
+++ b/hw/syborg_serial.c
@@ -315,12 +315,6 @@ static int syborg_serial_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-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);
@@ -332,7 +326,8 @@ 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_handlers, s);
+        qemu_chr_add_handlers(s->chr, syborg_serial_can_receive,
+                              syborg_serial_receive, syborg_serial_event, 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 f6706ca..2979c9d 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -476,12 +476,6 @@ 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);
@@ -494,7 +488,8 @@ static int usb_serial_initfn(USBDevice *dev)
         return -1;
     }
 
-    qemu_chr_add_handlers(s->cs, &usb_serial_handlers, s);
+    qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
+                          usb_serial_event, s);
     usb_serial_handle_reset(dev);
     return 0;
 }
diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index 434c160..b0f5c07 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -100,21 +100,8 @@ 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 const QemuChrHandlers chr_handlers_no_flow_control = {
-    .fd_can_read = chr_can_read,
-    .fd_read = chr_read,
-    .fd_event = chr_event,
-};
-
 static int virtconsole_initfn(VirtIOSerialPort *port)
 {
-    static const QemuChrHandlers *handlers;
     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
     VirtIOSerialPortInfo *info = DO_UPCAST(VirtIOSerialPortInfo, qdev,
                                            vcon->port.dev.info);
@@ -125,13 +112,9 @@ static int virtconsole_initfn(VirtIOSerialPort *port)
     }
 
     if (vcon->chr) {
-        handlers = &chr_handlers;
-        if (!virtio_serial_flow_control_enabled(&vcon->port)) {
-            handlers = &chr_handlers_no_flow_control;
-        }
-        qemu_chr_add_handlers(vcon->chr, handlers, vcon);
+        qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
+                              vcon);
     }
-
     return 0;
 }
 
diff --git a/hw/xen_console.c b/hw/xen_console.c
index 8327e4e..d2261f4 100644
--- a/hw/xen_console.c
+++ b/hw/xen_console.c
@@ -202,11 +202,6 @@ 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);
@@ -227,9 +222,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_handlers, con);
-    }
+    if (con->chr)
+        qemu_chr_add_handlers(con->chr, xencons_can_receive, xencons_receive,
+                              NULL, con);
 
     xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
 		  con->ring_ref,
@@ -243,9 +238,8 @@ 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);
-    }
+    if (con->chr)
+        qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
     xen_be_unbind_evtchn(&con->xendev);
 
     if (con->sring) {
diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
index 66f0396..adab759 100644
--- a/hw/xilinx_uartlite.c
+++ b/hw/xilinx_uartlite.c
@@ -193,12 +193,6 @@ 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);
@@ -211,9 +205,8 @@ 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_handlers, s);
-    }
+    if (s->chr)
+        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
     return 0;
 }
 
diff --git a/monitor.c b/monitor.c
index 4eff1ae..d9204e4 100644
--- a/monitor.c
+++ b/monitor.c
@@ -5097,18 +5097,6 @@ 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;
@@ -5131,12 +5119,13 @@ 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_control_handlers, mon);
+        qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read,
+                              monitor_control_event, mon);
         qemu_chr_set_echo(chr, true);
     } else {
-        qemu_chr_add_handlers(chr, &monitor_handlers, mon);
+        qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
+                              monitor_event, mon);
     }
 
     QLIST_INSERT_HEAD(&mon_list, mon, entry);
diff --git a/net/slirp.c b/net/slirp.c
index e818f2e..99b42e8 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -573,11 +573,6 @@ 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)
 {
@@ -634,7 +629,8 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
     fwd->port = port;
     fwd->slirp = s->slirp;
 
-    qemu_chr_add_handlers(fwd->hd, &guestfwd_handlers, fwd);
+    qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
+                          NULL, fwd);
     return 0;
 
  fail_syntax:
diff --git a/qemu-char.c b/qemu-char.c
index 6df63b3..86bb1cb 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -191,26 +191,19 @@ 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,
-                           const QemuChrHandlers *handlers, void *opaque)
+                           IOCanRWHandler *fd_can_read,
+                           IOReadHandler *fd_read,
+                           IOEventHandler *fd_event,
+                           void *opaque)
 {
-    if (!s) {
-        return;
-    }
-    if (!opaque && !handlers) {
+    if (!opaque && !fd_can_read && !fd_read && !fd_event) {
         /* chr driver being released. */
         ++s->avail_connections;
     }
-    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->chr_can_read = fd_can_read;
+    s->chr_read = fd_read;
+    s->chr_event = fd_event;
     s->handler_opaque = opaque;
     if (s->chr_update_read_handler)
         s->chr_update_read_handler(s);
@@ -453,12 +446,6 @@ 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;
@@ -473,7 +460,8 @@ 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_handlers, chr);
+        qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read,
+                              mux_chr_event, 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 d2332c7..71222c7 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -1,7 +1,6 @@
 #ifndef QEMU_CHAR_H
 #define QEMU_CHAR_H
 
-#include <stdbool.h>
 #include "qemu-common.h"
 #include "qemu-queue.h"
 #include "qemu-option.h"
@@ -77,13 +76,6 @@ struct CharDriverState {
     QTAILQ_ENTRY(CharDriverState) next;
 };
 
-typedef struct QemuChrHandlers {
-    IOCanRWHandler *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));
@@ -95,7 +87,10 @@ void qemu_chr_close(CharDriverState *chr);
 void qemu_chr_printf(CharDriverState *s, const char *fmt, ...);
 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, const QemuChrHandlers *handlers,
+void qemu_chr_add_handlers(CharDriverState *s,
+                           IOCanRWHandler *fd_can_read,
+                           IOReadHandler *fd_read,
+                           IOEventHandler *fd_event,
                            void *opaque);
 void qemu_chr_event(CharDriverState *s, int event);
 int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg);
diff --git a/usb-redir.c b/usb-redir.c
index 420d3a3..93c0f19 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -1025,12 +1025,6 @@ static void usbredir_chardev_event(void *opaque, int event)
  * init + destroy
  */
 
-static QemuChrHandlers usbredir_handlers = {
-    .fd_can_read = usbredir_chardev_can_read,
-    .fd_read = usbredir_chardev_read,
-    .fd_event = usbredir_chardev_event,
-};
-
 static void usbredir_vm_state_change(void *priv, int running, RunState state)
 {
     USBRedirDevice *dev = priv;
@@ -1075,7 +1069,8 @@ static int usbredir_initfn(USBDevice *udev)
 
     /* Let the backend know we are ready */
     qemu_chr_guest_open(dev->cs);
-    qemu_chr_add_handlers(dev->cs, &usbredir_handlers, dev);
+    qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
+                          usbredir_chardev_read, usbredir_chardev_event, dev);
 
     qemu_add_vm_change_state_handler(usbredir_vm_state_change, dev);
     return 0;
-- 
1.7.11.7