252f3af
>From 003cc09f8fc34e7571ebd4a89ea6aa6324a80b54 Mon Sep 17 00:00:00 2001
252f3af
From: Amit Shah <amit.shah@redhat.com>
252f3af
Date: Mon, 21 Mar 2011 20:31:45 +0100
252f3af
Subject: [PATCH 06/19] char: Add a QemuChrHandlers struct to initialise chardev handlers
252f3af
252f3af
Instead of passing each handler in the qemu_add_handlers() function,
252f3af
create a struct of handlers that can be passed to the function instead.
252f3af
252f3af
Signed-off-by: Amit Shah <amit.shah@redhat.com>
252f3af
---
252f3af
 gdbstub.c            |    9 +++++++--
252f3af
 hw/debugcon.c        |    2 +-
252f3af
 hw/escc.c            |    9 +++++++--
252f3af
 hw/etraxfs_ser.c     |   13 +++++++++----
252f3af
 hw/grlib_apbuart.c   |   12 +++++++-----
252f3af
 hw/ivshmem.c         |   28 ++++++++++++++++++++++------
252f3af
 hw/mcf_uart.c        |    9 +++++++--
252f3af
 hw/pl011.c           |    9 +++++++--
252f3af
 hw/pxa2xx.c          |   13 +++++++++----
252f3af
 hw/serial.c          |    9 +++++++--
252f3af
 hw/sh_serial.c       |   12 +++++++++---
252f3af
 hw/syborg_serial.c   |    9 +++++++--
252f3af
 hw/usb-serial.c      |    9 +++++++--
252f3af
 hw/virtio-console.c  |    9 +++++++--
252f3af
 hw/xen_console.c     |   16 +++++++++++-----
252f3af
 hw/xilinx_uartlite.c |   11 +++++++++--
252f3af
 monitor.c            |   18 ++++++++++++++----
252f3af
 net/slirp.c          |    8 ++++++--
252f3af
 qemu-char.c          |   30 +++++++++++++++++++++---------
252f3af
 qemu-char.h          |   13 +++++++++----
252f3af
 20 files changed, 183 insertions(+), 65 deletions(-)
252f3af
252f3af
diff --git a/gdbstub.c b/gdbstub.c
252f3af
index 14e8b9b..4190ac7 100644
252f3af
--- a/gdbstub.c
252f3af
+++ b/gdbstub.c
252f3af
@@ -2634,6 +2634,12 @@ static void gdb_sigterm_handler(int signal)
252f3af
 }
252f3af
 #endif
252f3af
 
252f3af
+static const QemuChrHandlers gdb_handlers = {
252f3af
+    .fd_can_read = gdb_chr_can_receive,
252f3af
+    .fd_read = gdb_chr_receive,
252f3af
+    .fd_event = gdb_chr_event,
252f3af
+};
252f3af
+
252f3af
 int gdbserver_start(const char *device)
252f3af
 {
252f3af
     GDBState *s;
252f3af
@@ -2663,8 +2669,7 @@ int gdbserver_start(const char *device)
252f3af
         if (!chr)
252f3af
             return -1;
252f3af
 
252f3af
-        qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
252f3af
-                              gdb_chr_event, NULL);
252f3af
+        qemu_chr_add_handlers(chr, &gdb_handlers, NULL);
252f3af
     }
252f3af
 
252f3af
     s = gdbserver_state;
252f3af
diff --git a/hw/debugcon.c b/hw/debugcon.c
252f3af
index 5ee6821..e79a595 100644
252f3af
--- a/hw/debugcon.c
252f3af
+++ b/hw/debugcon.c
252f3af
@@ -73,7 +73,7 @@ static void debugcon_init_core(DebugconState *s)
252f3af
         exit(1);
252f3af
     }
252f3af
 
252f3af
-    qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s);
252f3af
+    qemu_chr_add_handlers(s->chr, NULL, s);
252f3af
 }
252f3af
 
252f3af
 static int debugcon_isa_initfn(ISADevice *dev)
252f3af
diff --git a/hw/escc.c b/hw/escc.c
252f3af
index f6fd919..dfa329a 100644
252f3af
--- a/hw/escc.c
252f3af
+++ b/hw/escc.c
252f3af
@@ -898,6 +898,12 @@ void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
252f3af
     sysbus_mmio_map(s, 0, base);
252f3af
 }
252f3af
 
252f3af
+static const QemuChrHandlers serial_handlers = {
252f3af
+    .fd_can_read = serial_can_receive,
252f3af
+    .fd_read = serial_receive1,
252f3af
+    .fd_event = serial_event,
252f3af
+};
252f3af
+
252f3af
 static int escc_init1(SysBusDevice *dev)
252f3af
 {
252f3af
     SerialState *s = FROM_SYSBUS(SerialState, dev);
252f3af
@@ -911,8 +917,7 @@ static int escc_init1(SysBusDevice *dev)
252f3af
         s->chn[i].chn = 1 - i;
252f3af
         s->chn[i].clock = s->frequency / 2;
252f3af
         if (s->chn[i].chr) {
252f3af
-            qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
252f3af
-                                  serial_receive1, serial_event, &s->chn[i]);
252f3af
+            qemu_chr_add_handlers(s->chn[i].chr, &serial_handlers, &s->chn[i]);
252f3af
         }
252f3af
     }
252f3af
     s->chn[0].otherchn = &s->chn[1];
252f3af
diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
252f3af
index 2787ebd..406121c 100644
252f3af
--- a/hw/etraxfs_ser.c
252f3af
+++ b/hw/etraxfs_ser.c
252f3af
@@ -190,6 +190,12 @@ static void serial_event(void *opaque, int event)
252f3af
 
252f3af
 }
252f3af
 
252f3af
+static const QemuChrHandlers serial_handlers = {
252f3af
+    .fd_can_read = serial_can_receive,
252f3af
+    .fd_read = serial_receive,
252f3af
+    .fd_event = serial_event,
252f3af
+};
252f3af
+
252f3af
 static int etraxfs_ser_init(SysBusDevice *dev)
252f3af
 {
252f3af
     struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
252f3af
@@ -204,10 +210,9 @@ static int etraxfs_ser_init(SysBusDevice *dev)
252f3af
                                       DEVICE_NATIVE_ENDIAN);
252f3af
     sysbus_init_mmio(dev, R_MAX * 4, ser_regs);
252f3af
     s->chr = qdev_init_chardev(&dev->qdev);
252f3af
-    if (s->chr)
252f3af
-        qemu_chr_add_handlers(s->chr,
252f3af
-                      serial_can_receive, serial_receive,
252f3af
-                      serial_event, s);
252f3af
+    if (s->chr) {
252f3af
+        qemu_chr_add_handlers(s->chr, &serial_handlers, s);
252f3af
+    }
252f3af
     return 0;
252f3af
 }
252f3af
 
252f3af
diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c
252f3af
index 101b150..40d6968 100644
252f3af
--- a/hw/grlib_apbuart.c
252f3af
+++ b/hw/grlib_apbuart.c
252f3af
@@ -144,16 +144,18 @@ static CPUWriteMemoryFunc * const grlib_apbuart_write[] = {
252f3af
     NULL, NULL, grlib_apbuart_writel,
252f3af
 };
252f3af
 
252f3af
+static const QemuChrHandlers grlib_handlers = {
252f3af
+    .fd_can_read = grlib_apbuart_can_receive,
252f3af
+    .fd_read = grlib_apbuart_receive,
252f3af
+    .fd_event = grlib_apbuart_event,
252f3af
+};
252f3af
+
252f3af
 static int grlib_apbuart_init(SysBusDevice *dev)
252f3af
 {
252f3af
     UART *uart      = FROM_SYSBUS(typeof(*uart), dev);
252f3af
     int   uart_regs = 0;
252f3af
 
252f3af
-    qemu_chr_add_handlers(uart->chr,
252f3af
-                          grlib_apbuart_can_receive,
252f3af
-                          grlib_apbuart_receive,
252f3af
-                          grlib_apbuart_event,
252f3af
-                          uart);
252f3af
+    qemu_chr_add_handlers(uart->chr, &grlib_handlers, uart);
252f3af
 
252f3af
     sysbus_init_irq(dev, &uart->irq);
252f3af
 
252f3af
diff --git a/hw/ivshmem.c b/hw/ivshmem.c
252f3af
index 7b19a81..ef8e5ce 100644
252f3af
--- a/hw/ivshmem.c
252f3af
+++ b/hw/ivshmem.c
252f3af
@@ -312,6 +312,18 @@ static void fake_irqfd(void *opaque, const uint8_t *buf, int size) {
252f3af
     msix_notify(pdev, entry->vector);
252f3af
 }
252f3af
 
252f3af
+static const QemuChrHandlers ivshmem_handlers = {
252f3af
+    .fd_can_read = ivshmem_can_receive,
252f3af
+    .fd_read = ivshmem_receive,
252f3af
+    .fd_event = ivshmem_event,
252f3af
+};
252f3af
+
252f3af
+static const QemuChrHandlers ivshmem_msi_handlers = {
252f3af
+    .fd_can_read = ivshmem_can_receive,
252f3af
+    .fd_read = fake_irqfd,
252f3af
+    .fd_event = ivshmem_event,
252f3af
+};
252f3af
+
252f3af
 static CharDriverState* create_eventfd_chr_device(void * opaque, int eventfd,
252f3af
                                                                     int vector)
252f3af
 {
252f3af
@@ -331,11 +343,10 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, int eventfd,
252f3af
         s->eventfd_table[vector].pdev = &s->dev;
252f3af
         s->eventfd_table[vector].vector = vector;
252f3af
 
252f3af
-        qemu_chr_add_handlers(chr, ivshmem_can_receive, fake_irqfd,
252f3af
-                      ivshmem_event, &s->eventfd_table[vector]);
252f3af
+        qemu_chr_add_handlers(chr, &ivshmem_msi_handlers,
252f3af
+                              &s->eventfd_table[vector]);
252f3af
     } else {
252f3af
-        qemu_chr_add_handlers(chr, ivshmem_can_receive, ivshmem_receive,
252f3af
-                      ivshmem_event, s);
252f3af
+        qemu_chr_add_handlers(chr, &ivshmem_handlers, s);
252f3af
     }
252f3af
 
252f3af
     return chr;
252f3af
@@ -666,6 +677,12 @@ static int ivshmem_load(QEMUFile* f, void *opaque, int version_id)
252f3af
     return 0;
252f3af
 }
252f3af
 
252f3af
+static const QemuChrHandlers ivshmem_server_handlers = {
252f3af
+    .fd_can_read = ivshmem_can_receive,
252f3af
+    .fd_read = ivshmem_read,
252f3af
+    .fd_event = ivshmem_event,
252f3af
+};
252f3af
+
252f3af
 static int pci_ivshmem_init(PCIDevice *dev)
252f3af
 {
252f3af
     IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev);
252f3af
@@ -754,8 +771,7 @@ static int pci_ivshmem_init(PCIDevice *dev)
252f3af
 
252f3af
         s->eventfd_chr = qemu_mallocz(s->vectors * sizeof(CharDriverState *));
252f3af
 
252f3af
-        qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive, ivshmem_read,
252f3af
-                     ivshmem_event, s);
252f3af
+        qemu_chr_add_handlers(s->server_chr, &ivshmem_server_handlers, s);
252f3af
     } else {
252f3af
         /* just map the file immediately, we're not using a server */
252f3af
         int fd;
252f3af
diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c
252f3af
index db57096..9928c11 100644
252f3af
--- a/hw/mcf_uart.c
252f3af
+++ b/hw/mcf_uart.c
252f3af
@@ -268,6 +268,12 @@ static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size)
252f3af
     mcf_uart_push_byte(s, buf[0]);
252f3af
 }
252f3af
 
252f3af
+static const QemuChrHandlers mcf_uart_handlers = {
252f3af
+    .fd_can_read = mcf_uart_can_receive,
252f3af
+    .fd_read = mcf_uart_receive,
252f3af
+    .fd_event = mcf_uart_event,
252f3af
+};
252f3af
+
252f3af
 void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
252f3af
 {
252f3af
     mcf_uart_state *s;
252f3af
@@ -276,8 +282,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
252f3af
     s->chr = chr;
252f3af
     s->irq = irq;
252f3af
     if (chr) {
252f3af
-        qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
252f3af
-                              mcf_uart_event, s);
252f3af
+        qemu_chr_add_handlers(chr, &mcf_uart_handlers, s);
252f3af
     }
252f3af
     mcf_uart_reset(s);
252f3af
     return s;
252f3af
diff --git a/hw/pl011.c b/hw/pl011.c
252f3af
index 77f0dbf..d93c655 100644
252f3af
--- a/hw/pl011.c
252f3af
+++ b/hw/pl011.c
252f3af
@@ -286,6 +286,12 @@ static int pl011_load(QEMUFile *f, void *opaque, int version_id)
252f3af
     return 0;
252f3af
 }
252f3af
 
252f3af
+static const QemuChrHandlers pl011_handlers = {
252f3af
+    .fd_can_read = pl011_can_receive,
252f3af
+    .fd_read = pl011_receive,
252f3af
+    .fd_event = pl011_event,
252f3af
+};
252f3af
+
252f3af
 static int pl011_init(SysBusDevice *dev, const unsigned char *id)
252f3af
 {
252f3af
     int iomemtype;
252f3af
@@ -304,8 +310,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
252f3af
     s->cr = 0x300;
252f3af
     s->flags = 0x90;
252f3af
     if (s->chr) {
252f3af
-        qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
252f3af
-                              pl011_event, s);
252f3af
+        qemu_chr_add_handlers(s->chr, &pl011_handlers, s);
252f3af
     }
252f3af
     register_savevm(&dev->qdev, "pl011_uart", -1, 1, pl011_save, pl011_load, s);
252f3af
     return 0;
252f3af
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
252f3af
index d966846..d7ebf33 100644
252f3af
--- a/hw/pxa2xx.c
252f3af
+++ b/hw/pxa2xx.c
252f3af
@@ -1995,6 +1995,12 @@ static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id)
252f3af
     return 0;
252f3af
 }
252f3af
 
252f3af
+static const QemuChrHandlers pxa2xx_handlers = {
252f3af
+    .fd_can_read = pxa2xx_fir_is_empty,
252f3af
+    .fd_read = pxa2xx_fir_rx,
252f3af
+    .fd_event = pxa2xx_fir_event,
252f3af
+};
252f3af
+
252f3af
 static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
252f3af
                 qemu_irq irq, PXA2xxDMAState *dma,
252f3af
                 CharDriverState *chr)
252f3af
@@ -2013,10 +2019,9 @@ static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
252f3af
                     pxa2xx_fir_writefn, s, DEVICE_NATIVE_ENDIAN);
252f3af
     cpu_register_physical_memory(base, 0x1000, iomemtype);
252f3af
 
252f3af
-    if (chr)
252f3af
-        qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
252f3af
-                        pxa2xx_fir_rx, pxa2xx_fir_event, s);
252f3af
-
252f3af
+    if (chr) {
252f3af
+        qemu_chr_add_handlers(chr, &pxa2xx_handlers, s);
252f3af
+    }
252f3af
     register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
252f3af
                     pxa2xx_fir_load, s);
252f3af
 
252f3af
diff --git a/hw/serial.c b/hw/serial.c
252f3af
index 2c4af61..65265e2 100644
252f3af
--- a/hw/serial.c
252f3af
+++ b/hw/serial.c
252f3af
@@ -727,6 +727,12 @@ static void serial_reset(void *opaque)
252f3af
     qemu_irq_lower(s->irq);
252f3af
 }
252f3af
 
252f3af
+static const QemuChrHandlers serial_handlers = {
252f3af
+    .fd_can_read = serial_can_receive1,
252f3af
+    .fd_read = serial_receive1,
252f3af
+    .fd_event = serial_event,
252f3af
+};
252f3af
+
252f3af
 static void serial_init_core(SerialState *s)
252f3af
 {
252f3af
     if (!s->chr) {
252f3af
@@ -741,8 +747,7 @@ static void serial_init_core(SerialState *s)
252f3af
 
252f3af
     qemu_register_reset(serial_reset, s);
252f3af
 
252f3af
-    qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
252f3af
-                          serial_event, s);
252f3af
+    qemu_chr_add_handlers(s->chr, &serial_handlers, s);
252f3af
 }
252f3af
 
252f3af
 /* Change the main reference oscillator frequency. */
252f3af
diff --git a/hw/sh_serial.c b/hw/sh_serial.c
252f3af
index 191f4a6..8b6460d 100644
252f3af
--- a/hw/sh_serial.c
252f3af
+++ b/hw/sh_serial.c
252f3af
@@ -350,6 +350,12 @@ static CPUWriteMemoryFunc * const sh_serial_writefn[] = {
252f3af
     &sh_serial_write,
252f3af
 };
252f3af
 
252f3af
+static const QemuChrHandlers sh_serial_handlers = {
252f3af
+    .fd_can_read = sh_serial_can_receive1,
252f3af
+    .fd_read = sh_serial_receive1,
252f3af
+    .fd_event = sh_serial_event,
252f3af
+};
252f3af
+
252f3af
 void sh_serial_init (target_phys_addr_t base, int feat,
252f3af
 		     uint32_t freq, CharDriverState *chr,
252f3af
 		     qemu_irq eri_source,
252f3af
@@ -389,9 +395,9 @@ void sh_serial_init (target_phys_addr_t base, int feat,
252f3af
 
252f3af
     s->chr = chr;
252f3af
 
252f3af
-    if (chr)
252f3af
-        qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
252f3af
-			      sh_serial_event, s);
252f3af
+    if (chr) {
252f3af
+        qemu_chr_add_handlers(chr, &sh_serial_handlers, s);
252f3af
+    }
252f3af
 
252f3af
     s->eri = eri_source;
252f3af
     s->rxi = rxi_source;
252f3af
diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
252f3af
index 34ce076..124b636 100644
252f3af
--- a/hw/syborg_serial.c
252f3af
+++ b/hw/syborg_serial.c
252f3af
@@ -315,6 +315,12 @@ static int syborg_serial_load(QEMUFile *f, void *opaque, int version_id)
252f3af
     return 0;
252f3af
 }
252f3af
 
252f3af
+static const QemuChrHandlers syborg_serial_handlers = {
252f3af
+    .fd_can_read = syborg_serial_can_receive,
252f3af
+    .fd_read = syborg_serial_receive,
252f3af
+    .fd_event = syborg_serial_event,
252f3af
+};
252f3af
+
252f3af
 static int syborg_serial_init(SysBusDevice *dev)
252f3af
 {
252f3af
     SyborgSerialState *s = FROM_SYSBUS(SyborgSerialState, dev);
252f3af
@@ -327,8 +333,7 @@ static int syborg_serial_init(SysBusDevice *dev)
252f3af
     sysbus_init_mmio(dev, 0x1000, iomemtype);
252f3af
     s->chr = qdev_init_chardev(&dev->qdev);
252f3af
     if (s->chr) {
252f3af
-        qemu_chr_add_handlers(s->chr, syborg_serial_can_receive,
252f3af
-                              syborg_serial_receive, syborg_serial_event, s);
252f3af
+        qemu_chr_add_handlers(s->chr, &syborg_serial_handlers, s);
252f3af
     }
252f3af
     if (s->fifo_size <= 0) {
252f3af
         fprintf(stderr, "syborg_serial: fifo too small\n");
252f3af
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
252f3af
index 6763d52..2435d9d 100644
252f3af
--- a/hw/usb-serial.c
252f3af
+++ b/hw/usb-serial.c
252f3af
@@ -475,6 +475,12 @@ static void usb_serial_event(void *opaque, int event)
252f3af
     }
252f3af
 }
252f3af
 
252f3af
+static const QemuChrHandlers usb_serial_handlers = {
252f3af
+    .fd_can_read = usb_serial_can_read,
252f3af
+    .fd_read = usb_serial_read,
252f3af
+    .fd_event = usb_serial_event,
252f3af
+};
252f3af
+
252f3af
 static int usb_serial_initfn(USBDevice *dev)
252f3af
 {
252f3af
     USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
252f3af
@@ -486,8 +492,7 @@ static int usb_serial_initfn(USBDevice *dev)
252f3af
         return -1;
252f3af
     }
252f3af
 
252f3af
-    qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
252f3af
-                          usb_serial_event, s);
252f3af
+    qemu_chr_add_handlers(s->cs, &usb_serial_handlers, s);
252f3af
     usb_serial_handle_reset(dev);
252f3af
     return 0;
252f3af
 }
252f3af
diff --git a/hw/virtio-console.c b/hw/virtio-console.c
252f3af
index 62624ec..22cf28c 100644
252f3af
--- a/hw/virtio-console.c
252f3af
+++ b/hw/virtio-console.c
252f3af
@@ -57,13 +57,18 @@ static void chr_event(void *opaque, int event)
252f3af
     }
252f3af
 }
252f3af
 
252f3af
+static const QemuChrHandlers chr_handlers = {
252f3af
+    .fd_can_read = chr_can_read,
252f3af
+    .fd_read = chr_read,
252f3af
+    .fd_event = chr_event,
252f3af
+};
252f3af
+
252f3af
 static int generic_port_init(VirtConsole *vcon, VirtIOSerialDevice *dev)
252f3af
 {
252f3af
     vcon->port.info = dev->info;
252f3af
 
252f3af
     if (vcon->chr) {
252f3af
-        qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
252f3af
-                              vcon);
252f3af
+        qemu_chr_add_handlers(vcon->chr, &chr_handlers, vcon);
252f3af
         vcon->port.info->have_data = flush_buf;
252f3af
     }
252f3af
     return 0;
252f3af
diff --git a/hw/xen_console.c b/hw/xen_console.c
252f3af
index d2261f4..8327e4e 100644
252f3af
--- a/hw/xen_console.c
252f3af
+++ b/hw/xen_console.c
252f3af
@@ -202,6 +202,11 @@ static int con_init(struct XenDevice *xendev)
252f3af
     return 0;
252f3af
 }
252f3af
 
252f3af
+static const QemuChrHandlers xencons_handlers = {
252f3af
+    .fd_can_read = xencons_can_receive,
252f3af
+    .fd_read = xencons_receive,
252f3af
+};
252f3af
+
252f3af
 static int con_connect(struct XenDevice *xendev)
252f3af
 {
252f3af
     struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
252f3af
@@ -222,9 +227,9 @@ static int con_connect(struct XenDevice *xendev)
252f3af
 	return -1;
252f3af
 
252f3af
     xen_be_bind_evtchn(&con->xendev);
252f3af
-    if (con->chr)
252f3af
-        qemu_chr_add_handlers(con->chr, xencons_can_receive, xencons_receive,
252f3af
-                              NULL, con);
252f3af
+    if (con->chr) {
252f3af
+        qemu_chr_add_handlers(con->chr, &xencons_handlers, con);
252f3af
+    }
252f3af
 
252f3af
     xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
252f3af
 		  con->ring_ref,
252f3af
@@ -238,8 +243,9 @@ static void con_disconnect(struct XenDevice *xendev)
252f3af
 {
252f3af
     struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
252f3af
 
252f3af
-    if (con->chr)
252f3af
-        qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
252f3af
+    if (con->chr) {
252f3af
+        qemu_chr_add_handlers(con->chr, NULL, NULL);
252f3af
+    }
252f3af
     xen_be_unbind_evtchn(&con->xendev);
252f3af
 
252f3af
     if (con->sring) {
252f3af
diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
252f3af
index 9b94e98..1845577 100644
252f3af
--- a/hw/xilinx_uartlite.c
252f3af
+++ b/hw/xilinx_uartlite.c
252f3af
@@ -193,6 +193,12 @@ static void uart_event(void *opaque, int event)
252f3af
 
252f3af
 }
252f3af
 
252f3af
+static const QemuChrHandlers uart_handlers = {
252f3af
+    .fd_can_read = uart_can_rx,
252f3af
+    .fd_read = uart_rx,
252f3af
+    .fd_event = uart_event,
252f3af
+};
252f3af
+
252f3af
 static int xilinx_uartlite_init(SysBusDevice *dev)
252f3af
 {
252f3af
     struct xlx_uartlite *s = FROM_SYSBUS(typeof (*s), dev);
252f3af
@@ -206,8 +212,9 @@ static int xilinx_uartlite_init(SysBusDevice *dev)
252f3af
     sysbus_init_mmio(dev, R_MAX * 4, uart_regs);
252f3af
 
252f3af
     s->chr = qdev_init_chardev(&dev->qdev);
252f3af
-    if (s->chr)
252f3af
-        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
252f3af
+    if (s->chr) {
252f3af
+        qemu_chr_add_handlers(s->chr, &uart_handlers, s);
252f3af
+    }
252f3af
     return 0;
252f3af
 }
252f3af
 
252f3af
diff --git a/monitor.c b/monitor.c
252f3af
index 096d42b..a00a233 100644
252f3af
--- a/monitor.c
252f3af
+++ b/monitor.c
252f3af
@@ -5179,6 +5179,18 @@ static void monitor_event(void *opaque, int event)
252f3af
  * End:
252f3af
  */
252f3af
 
252f3af
+static const QemuChrHandlers monitor_handlers = {
252f3af
+    .fd_can_read = monitor_can_read,
252f3af
+    .fd_read = monitor_read,
252f3af
+    .fd_event = monitor_event,
252f3af
+};
252f3af
+
252f3af
+static const QemuChrHandlers monitor_control_handlers = {
252f3af
+    .fd_can_read = monitor_can_read,
252f3af
+    .fd_read = monitor_control_read,
252f3af
+    .fd_event = monitor_control_event,
252f3af
+};
252f3af
+
252f3af
 void monitor_init(CharDriverState *chr, int flags)
252f3af
 {
252f3af
     static int is_first_init = 1;
252f3af
@@ -5201,12 +5213,10 @@ void monitor_init(CharDriverState *chr, int flags)
252f3af
     if (monitor_ctrl_mode(mon)) {
252f3af
         mon->mc = qemu_mallocz(sizeof(MonitorControl));
252f3af
         /* Control mode requires special handlers */
252f3af
-        qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read,
252f3af
-                              monitor_control_event, mon);
252f3af
+        qemu_chr_add_handlers(chr, &monitor_control_handlers, mon);
252f3af
         qemu_chr_set_echo(chr, true);
252f3af
     } else {
252f3af
-        qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
252f3af
-                              monitor_event, mon);
252f3af
+        qemu_chr_add_handlers(chr, &monitor_handlers, mon);
252f3af
     }
252f3af
 
252f3af
     QLIST_INSERT_HEAD(&mon_list, mon, entry);
252f3af
diff --git a/net/slirp.c b/net/slirp.c
252f3af
index b41c60a..437be46 100644
252f3af
--- a/net/slirp.c
252f3af
+++ b/net/slirp.c
252f3af
@@ -577,6 +577,11 @@ static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
252f3af
     slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size);
252f3af
 }
252f3af
 
252f3af
+static const QemuChrHandlers guestfwd_handlers = {
252f3af
+    .fd_can_read = guestfwd_can_read,
252f3af
+    .fd_read = guestfwd_read,
252f3af
+};
252f3af
+
252f3af
 static int slirp_guestfwd(SlirpState *s, const char *config_str,
252f3af
                           int legacy_format)
252f3af
 {
252f3af
@@ -633,8 +638,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
252f3af
     fwd->port = port;
252f3af
     fwd->slirp = s->slirp;
252f3af
 
252f3af
-    qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
252f3af
-                          NULL, fwd);
252f3af
+    qemu_chr_add_handlers(fwd->hd, &guestfwd_handlers, fwd);
252f3af
     return 0;
252f3af
 
252f3af
  fail_syntax:
252f3af
diff --git a/qemu-char.c b/qemu-char.c
252f3af
index 4b57af9..3a31d8b 100644
252f3af
--- a/qemu-char.c
252f3af
+++ b/qemu-char.c
252f3af
@@ -191,15 +191,22 @@ void qemu_chr_send_event(CharDriverState *s, int event)
252f3af
         s->chr_send_event(s, event);
252f3af
 }
252f3af
 
252f3af
+static const QemuChrHandlers null_handlers = {
252f3af
+    /* All handlers are initialised to NULL */
252f3af
+};
252f3af
+
252f3af
 void qemu_chr_add_handlers(CharDriverState *s,
252f3af
-                           IOCanReadHandler *fd_can_read,
252f3af
-                           IOReadHandler *fd_read,
252f3af
-                           IOEventHandler *fd_event,
252f3af
-                           void *opaque)
252f3af
-{
252f3af
-    s->chr_can_read = fd_can_read;
252f3af
-    s->chr_read = fd_read;
252f3af
-    s->chr_event = fd_event;
252f3af
+                           const QemuChrHandlers *handlers, void *opaque)
252f3af
+{
252f3af
+    if (!s) {
252f3af
+        return;
252f3af
+    }
252f3af
+    if (!handlers) {
252f3af
+        handlers = &null_handlers;
252f3af
+    }
252f3af
+    s->chr_can_read = handlers->fd_can_read;
252f3af
+    s->chr_read = handlers->fd_read;
252f3af
+    s->chr_event = handlers->fd_event;
252f3af
     s->handler_opaque = opaque;
252f3af
     if (s->chr_update_read_handler)
252f3af
         s->chr_update_read_handler(s);
252f3af
@@ -437,6 +444,12 @@ static void mux_chr_event(void *opaque, int event)
252f3af
         mux_chr_send_event(d, i, event);
252f3af
 }
252f3af
 
252f3af
+static const QemuChrHandlers mux_chr_handlers = {
252f3af
+    .fd_can_read = mux_chr_can_read,
252f3af
+    .fd_read = mux_chr_read,
252f3af
+    .fd_event = mux_chr_event,
252f3af
+};
252f3af
+
252f3af
 static void mux_chr_update_read_handler(CharDriverState *chr)
252f3af
 {
252f3af
     MuxDriver *d = chr->opaque;
252f3af
@@ -451,8 +464,7 @@ static void mux_chr_update_read_handler(CharDriverState *chr)
252f3af
     d->chr_event[d->mux_cnt] = chr->chr_event;
252f3af
     /* Fix up the real driver with mux routines */
252f3af
     if (d->mux_cnt == 0) {
252f3af
-        qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read,
252f3af
-                              mux_chr_event, chr);
252f3af
+        qemu_chr_add_handlers(d->drv, &mux_chr_handlers, chr);
252f3af
     }
252f3af
     if (d->focus != -1) {
252f3af
         mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
252f3af
diff --git a/qemu-char.h b/qemu-char.h
252f3af
index 56d9954..7a1924c 100644
252f3af
--- a/qemu-char.h
252f3af
+++ b/qemu-char.h
252f3af
@@ -1,6 +1,7 @@
252f3af
 #ifndef QEMU_CHAR_H
252f3af
 #define QEMU_CHAR_H
252f3af
 
252f3af
+#include <stdbool.h>
252f3af
 #include "qemu-common.h"
252f3af
 #include "qemu-queue.h"
252f3af
 #include "qemu-option.h"
252f3af
@@ -73,6 +74,13 @@ struct CharDriverState {
252f3af
     QTAILQ_ENTRY(CharDriverState) next;
252f3af
 };
252f3af
 
252f3af
+typedef struct QemuChrHandlers {
252f3af
+    IOCanReadHandler *fd_can_read;
252f3af
+    IOReadHandler *fd_read;
252f3af
+    IOHandler *fd_write_unblocked;
252f3af
+    IOEventHandler *fd_event;
252f3af
+} QemuChrHandlers;
252f3af
+
252f3af
 QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
252f3af
 CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
252f3af
                                     void (*init)(struct CharDriverState *s));
252f3af
@@ -83,10 +91,7 @@ void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
252f3af
     GCC_FMT_ATTR(2, 3);
252f3af
 int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
252f3af
 void qemu_chr_send_event(CharDriverState *s, int event);
252f3af
-void qemu_chr_add_handlers(CharDriverState *s,
252f3af
-                           IOCanReadHandler *fd_can_read,
252f3af
-                           IOReadHandler *fd_read,
252f3af
-                           IOEventHandler *fd_event,
252f3af
+void qemu_chr_add_handlers(CharDriverState *s, const QemuChrHandlers *handlers,
252f3af
                            void *opaque);
252f3af
 int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg);
252f3af
 void qemu_chr_generic_open(CharDriverState *s);
252f3af
-- 
252f3af
1.7.4.1
252f3af