Change requested in launchpad bug #1288352
[packages/centos6/qemu.git] / 0401-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch
1 From 5f3ba69a09688b40a4648e8818e4878ae20fc2f6 Mon Sep 17 00:00:00 2001
2 From: Amit Shah <amit.shah@redhat.com>
3 Date: Mon, 21 Mar 2011 20:31:45 +0100
4 Subject: [PATCH] char: Add a QemuChrHandlers struct to initialise chardev
5  handlers
6
7 Instead of passing each handler in the qemu_add_handlers() function,
8 create a struct of handlers that can be passed to the function instead.
9
10 Signed-off-by: Amit Shah <amit.shah@redhat.com>
11 Signed-off-by: Cole Robinson <crobinso@redhat.com>
12 ---
13  gdbstub.c               |  9 +++++++--
14  hw/cadence_uart.c       |  9 +++++++--
15  hw/ccid-card-passthru.c | 11 +++++++----
16  hw/debugcon.c           |  2 +-
17  hw/escc.c               |  9 +++++++--
18  hw/etraxfs_ser.c        | 13 +++++++++----
19  hw/exynos4210_uart.c    |  9 +++++++--
20  hw/grlib_apbuart.c      | 12 +++++++-----
21  hw/imx_serial.c         |  9 +++++++--
22  hw/ivshmem.c            | 28 ++++++++++++++++++++++------
23  hw/lm32_juart.c         |  8 +++++++-
24  hw/lm32_uart.c          |  8 +++++++-
25  hw/mcf_uart.c           |  9 +++++++--
26  hw/milkymist-uart.c     |  8 +++++++-
27  hw/pl011.c              |  9 +++++++--
28  hw/pxa2xx.c             | 13 +++++++++----
29  hw/qdev-properties.c    |  2 +-
30  hw/serial.c             |  9 +++++++--
31  hw/sh_serial.c          | 12 +++++++++---
32  hw/spapr_vty.c          |  8 ++++++--
33  hw/strongarm.c          | 12 +++++++-----
34  hw/usb/dev-serial.c     |  9 +++++++--
35  hw/usb/redirect.c       |  9 +++++++--
36  hw/virtio-console.c     |  9 +++++++--
37  hw/xen_console.c        | 16 +++++++++++-----
38  hw/xilinx_uartlite.c    | 11 +++++++++--
39  monitor.c               | 18 ++++++++++++++----
40  net/slirp.c             |  8 ++++++--
41  qemu-char.c             | 32 ++++++++++++++++++++++----------
42  qemu-char.h             | 13 +++++++++----
43  qtest.c                 |  9 ++++++++-
44  31 files changed, 255 insertions(+), 88 deletions(-)
45
46 diff --git a/gdbstub.c b/gdbstub.c
47 index a91709f..b905c15 100644
48 --- a/gdbstub.c
49 +++ b/gdbstub.c
50 @@ -2965,6 +2965,12 @@ static void gdb_sigterm_handler(int signal)
51  }
52  #endif
53  
54 +static const QemuChrHandlers gdb_handlers = {
55 +    .fd_can_read = gdb_chr_can_receive,
56 +    .fd_read = gdb_chr_receive,
57 +    .fd_event = gdb_chr_event,
58 +};
59 +
60  int gdbserver_start(const char *device)
61  {
62      GDBState *s;
63 @@ -2994,8 +3000,7 @@ int gdbserver_start(const char *device)
64          if (!chr)
65              return -1;
66  
67 -        qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
68 -                              gdb_chr_event, NULL);
69 +        qemu_chr_add_handlers(chr, &gdb_handlers, NULL);
70      }
71  
72      s = gdbserver_state;
73 diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c
74 index f8afc4e..c9d3b21 100644
75 --- a/hw/cadence_uart.c
76 +++ b/hw/cadence_uart.c
77 @@ -435,6 +435,12 @@ static void cadence_uart_reset(UartState *s)
78      s->rx_wpos = 0;
79  }
80  
81 +static const QemuChrHandlers cadence_uart_handlers = {
82 +    .fd_can_read = uart_can_receive,
83 +    .fd_read = uart_receive,
84 +    .fd_event = uart_event,
85 +};
86 +
87  static int cadence_uart_init(SysBusDevice *dev)
88  {
89      UartState *s = FROM_SYSBUS(UartState, dev);
90 @@ -456,8 +462,7 @@ static int cadence_uart_init(SysBusDevice *dev)
91      cadence_uart_reset(s);
92  
93      if (s->chr) {
94 -        qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive,
95 -                              uart_event, s);
96 +        qemu_chr_add_handlers(s->chr, &cadence_uart_handlers, s);
97      }
98  
99      return 0;
100 diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
101 index bd6c777..fb32107 100644
102 --- a/hw/ccid-card-passthru.c
103 +++ b/hw/ccid-card-passthru.c
104 @@ -274,6 +274,12 @@ static const uint8_t *passthru_get_atr(CCIDCardState *base, uint32_t *len)
105      return card->atr;
106  }
107  
108 +static const QemuChrHandlers passthru_handlers = {
109 +    .fd_can_read = ccid_card_vscard_can_read,
110 +    .fd_read = ccid_card_vscard_read,
111 +    .fd_event = ccid_card_vscard_event,
112 +};
113 +
114  static int passthru_initfn(CCIDCardState *base)
115  {
116      PassthruState *card = DO_UPCAST(PassthruState, base, base);
117 @@ -282,10 +288,7 @@ static int passthru_initfn(CCIDCardState *base)
118      card->vscard_in_hdr = 0;
119      if (card->cs) {
120          DPRINTF(card, D_INFO, "initing chardev\n");
121 -        qemu_chr_add_handlers(card->cs,
122 -            ccid_card_vscard_can_read,
123 -            ccid_card_vscard_read,
124 -            ccid_card_vscard_event, card);
125 +        qemu_chr_add_handlers(card->cs, &passthru_handlers, card);
126          ccid_card_vscard_send_init(card);
127      } else {
128          error_report("missing chardev");
129 diff --git a/hw/debugcon.c b/hw/debugcon.c
130 index 14ab326..7887fd2 100644
131 --- a/hw/debugcon.c
132 +++ b/hw/debugcon.c
133 @@ -73,7 +73,7 @@ static void debugcon_init_core(DebugconState *s)
134          exit(1);
135      }
136  
137 -    qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s);
138 +    qemu_chr_add_handlers(s->chr, NULL, s);
139  }
140  
141  static int debugcon_isa_initfn(ISADevice *dev)
142 diff --git a/hw/escc.c b/hw/escc.c
143 index e1f5e73..ff9d8b1 100644
144 --- a/hw/escc.c
145 +++ b/hw/escc.c
146 @@ -867,6 +867,12 @@ void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
147      sysbus_mmio_map(s, 0, base);
148  }
149  
150 +static const QemuChrHandlers serial_handlers = {
151 +    .fd_can_read = serial_can_receive,
152 +    .fd_read = serial_receive1,
153 +    .fd_event = serial_event,
154 +};
155 +
156  static int escc_init1(SysBusDevice *dev)
157  {
158      SerialState *s = FROM_SYSBUS(SerialState, dev);
159 @@ -879,8 +885,7 @@ static int escc_init1(SysBusDevice *dev)
160          s->chn[i].chn = 1 - i;
161          s->chn[i].clock = s->frequency / 2;
162          if (s->chn[i].chr) {
163 -            qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
164 -                                  serial_receive1, serial_event, &s->chn[i]);
165 +            qemu_chr_add_handlers(s->chn[i].chr, &serial_handlers, &s->chn[i]);
166          }
167      }
168      s->chn[0].otherchn = &s->chn[1];
169 diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
170 index 5f16b17..f2571c2 100644
171 --- a/hw/etraxfs_ser.c
172 +++ b/hw/etraxfs_ser.c
173 @@ -208,6 +208,12 @@ static void etraxfs_ser_reset(DeviceState *d)
174  
175  }
176  
177 +static const QemuChrHandlers serial_handlers = {
178 +    .fd_can_read = serial_can_receive,
179 +    .fd_read = serial_receive,
180 +    .fd_event = serial_event,
181 +};
182 +
183  static int etraxfs_ser_init(SysBusDevice *dev)
184  {
185      struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
186 @@ -217,10 +223,9 @@ static int etraxfs_ser_init(SysBusDevice *dev)
187      sysbus_init_mmio(dev, &s->mmio);
188  
189      s->chr = qemu_char_get_next_serial();
190 -    if (s->chr)
191 -        qemu_chr_add_handlers(s->chr,
192 -                      serial_can_receive, serial_receive,
193 -                      serial_event, s);
194 +    if (s->chr) {
195 +        qemu_chr_add_handlers(s->chr, &serial_handlers, s);
196 +    }
197      return 0;
198  }
199  
200 diff --git a/hw/exynos4210_uart.c b/hw/exynos4210_uart.c
201 index ccc4780..fefe400 100644
202 --- a/hw/exynos4210_uart.c
203 +++ b/hw/exynos4210_uart.c
204 @@ -625,6 +625,12 @@ DeviceState *exynos4210_uart_create(target_phys_addr_t addr,
205      return dev;
206  }
207  
208 +static const QemuChrHandlers exynos4210_handlers = {
209 +    .fd_can_read = exynos4210_uart_can_receive,
210 +    .fd_read     = exynos4210_uart_receive,
211 +    .fd_event    = exynos4210_uart_event,
212 +};
213 +
214  static int exynos4210_uart_init(SysBusDevice *dev)
215  {
216      Exynos4210UartState *s = FROM_SYSBUS(Exynos4210UartState, dev);
217 @@ -636,8 +642,7 @@ static int exynos4210_uart_init(SysBusDevice *dev)
218  
219      sysbus_init_irq(dev, &s->irq);
220  
221 -    qemu_chr_add_handlers(s->chr, exynos4210_uart_can_receive,
222 -                          exynos4210_uart_receive, exynos4210_uart_event, s);
223 +    qemu_chr_add_handlers(s->chr, &exynos4210_handlers, s);
224  
225      return 0;
226  }
227 diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c
228 index 73fc989..fd77d52 100644
229 --- a/hw/grlib_apbuart.c
230 +++ b/hw/grlib_apbuart.c
231 @@ -222,15 +222,17 @@ static const MemoryRegionOps grlib_apbuart_ops = {
232      .endianness = DEVICE_NATIVE_ENDIAN,
233  };
234  
235 +static const QemuChrHandlers grlib_handlers = {
236 +    .fd_can_read = grlib_apbuart_can_receive,
237 +    .fd_read = grlib_apbuart_receive,
238 +    .fd_event = grlib_apbuart_event,
239 +};
240 +
241  static int grlib_apbuart_init(SysBusDevice *dev)
242  {
243      UART *uart = FROM_SYSBUS(typeof(*uart), dev);
244  
245 -    qemu_chr_add_handlers(uart->chr,
246 -                          grlib_apbuart_can_receive,
247 -                          grlib_apbuart_receive,
248 -                          grlib_apbuart_event,
249 -                          uart);
250 +    qemu_chr_add_handlers(uart->chr, &grlib_handlers, uart);
251  
252      sysbus_init_irq(dev, &uart->irq);
253  
254 diff --git a/hw/imx_serial.c b/hw/imx_serial.c
255 index d4eae43..f2304d2 100644
256 --- a/hw/imx_serial.c
257 +++ b/hw/imx_serial.c
258 @@ -381,6 +381,12 @@ static const struct MemoryRegionOps imx_serial_ops = {
259      .endianness = DEVICE_NATIVE_ENDIAN,
260  };
261  
262 +static const QemuChrHandlers imx_handlers = {
263 +    .fd_can_read = imx_can_receive,
264 +    .fd_read = imx_receive,
265 +    .fd_event = imx_event,
266 +};
267 +
268  static int imx_serial_init(SysBusDevice *dev)
269  {
270      IMXSerialState *s = FROM_SYSBUS(IMXSerialState, dev);
271 @@ -391,8 +397,7 @@ static int imx_serial_init(SysBusDevice *dev)
272      sysbus_init_irq(dev, &s->irq);
273  
274      if (s->chr) {
275 -        qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive,
276 -                              imx_event, s);
277 +        qemu_chr_add_handlers(s->chr, &imx_handlers, s);
278      } else {
279          DPRINTF("No char dev for uart at 0x%lx\n",
280                  (unsigned long)s->iomem.ram_addr);
281 diff --git a/hw/ivshmem.c b/hw/ivshmem.c
282 index 62fe53a..e90f691 100644
283 --- a/hw/ivshmem.c
284 +++ b/hw/ivshmem.c
285 @@ -273,6 +273,18 @@ static void fake_irqfd(void *opaque, const uint8_t *buf, int size) {
286      msix_notify(pdev, entry->vector);
287  }
288  
289 +static const QemuChrHandlers ivshmem_handlers = {
290 +    .fd_can_read = ivshmem_can_receive,
291 +    .fd_read = ivshmem_receive,
292 +    .fd_event = ivshmem_event,
293 +};
294 +
295 +static const QemuChrHandlers ivshmem_msi_handlers = {
296 +    .fd_can_read = ivshmem_can_receive,
297 +    .fd_read = fake_irqfd,
298 +    .fd_event = ivshmem_event,
299 +};
300 +
301  static CharDriverState* create_eventfd_chr_device(void * opaque, EventNotifier *n,
302                                                    int vector)
303  {
304 @@ -293,11 +305,10 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, EventNotifier *
305          s->eventfd_table[vector].pdev = &s->dev;
306          s->eventfd_table[vector].vector = vector;
307  
308 -        qemu_chr_add_handlers(chr, ivshmem_can_receive, fake_irqfd,
309 -                      ivshmem_event, &s->eventfd_table[vector]);
310 +        qemu_chr_add_handlers(chr, &ivshmem_msi_handlers,
311 +                              &s->eventfd_table[vector]);
312      } else {
313 -        qemu_chr_add_handlers(chr, ivshmem_can_receive, ivshmem_receive,
314 -                      ivshmem_event, s);
315 +        qemu_chr_add_handlers(chr, &ivshmem_handlers, s);
316      }
317  
318      return chr;
319 @@ -634,6 +645,12 @@ static void ivshmem_write_config(PCIDevice *pci_dev, uint32_t address,
320      msix_write_config(pci_dev, address, val, len);
321  }
322  
323 +static const QemuChrHandlers ivshmem_server_handlers = {
324 +    .fd_can_read = ivshmem_can_receive,
325 +    .fd_read = ivshmem_read,
326 +    .fd_event = ivshmem_event,
327 +};
328 +
329  static int pci_ivshmem_init(PCIDevice *dev)
330  {
331      IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev);
332 @@ -720,8 +737,7 @@ static int pci_ivshmem_init(PCIDevice *dev)
333  
334          s->eventfd_chr = g_malloc0(s->vectors * sizeof(CharDriverState *));
335  
336 -        qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive, ivshmem_read,
337 -                     ivshmem_event, s);
338 +        qemu_chr_add_handlers(s->server_chr, &ivshmem_server_handlers, s);
339      } else {
340          /* just map the file immediately, we're not using a server */
341          int fd;
342 diff --git a/hw/lm32_juart.c b/hw/lm32_juart.c
343 index f07ed39..d4daeb8 100644
344 --- a/hw/lm32_juart.c
345 +++ b/hw/lm32_juart.c
346 @@ -110,13 +110,19 @@ static void juart_reset(DeviceState *d)
347      s->jrx = 0;
348  }
349  
350 +static const QemuChrHandlers juart_handlers = {
351 +    .fd_can_read = juart_can_rx,
352 +    .fd_read = juart_rx,
353 +    .fd_event = juart_event,
354 +};
355 +
356  static int lm32_juart_init(SysBusDevice *dev)
357  {
358      LM32JuartState *s = FROM_SYSBUS(typeof(*s), dev);
359  
360      s->chr = qemu_char_get_next_serial();
361      if (s->chr) {
362 -        qemu_chr_add_handlers(s->chr, juart_can_rx, juart_rx, juart_event, s);
363 +        qemu_chr_add_handlers(s->chr, &juart_handlers, s);
364      }
365  
366      return 0;
367 diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c
368 index 57066e2..4ea130b 100644
369 --- a/hw/lm32_uart.c
370 +++ b/hw/lm32_uart.c
371 @@ -243,6 +243,12 @@ static void uart_reset(DeviceState *d)
372      s->regs[R_LSR] = LSR_THRE | LSR_TEMT;
373  }
374  
375 +static const QemuChrHandlers uart_handlers = {
376 +    .fd_can_read = uart_can_rx,
377 +    .fd_read = uart_rx,
378 +    .fd_event = uart_event,
379 +};
380 +
381  static int lm32_uart_init(SysBusDevice *dev)
382  {
383      LM32UartState *s = FROM_SYSBUS(typeof(*s), dev);
384 @@ -254,7 +260,7 @@ static int lm32_uart_init(SysBusDevice *dev)
385  
386      s->chr = qemu_char_get_next_serial();
387      if (s->chr) {
388 -        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
389 +        qemu_chr_add_handlers(s->chr, &uart_handlers, s);
390      }
391  
392      return 0;
393 diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c
394 index ec6a87f..f52fb96 100644
395 --- a/hw/mcf_uart.c
396 +++ b/hw/mcf_uart.c
397 @@ -272,6 +272,12 @@ static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size)
398      mcf_uart_push_byte(s, buf[0]);
399  }
400  
401 +static const QemuChrHandlers mcf_uart_handlers = {
402 +    .fd_can_read = mcf_uart_can_receive,
403 +    .fd_read = mcf_uart_receive,
404 +    .fd_event = mcf_uart_event,
405 +};
406 +
407  void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
408  {
409      mcf_uart_state *s;
410 @@ -280,8 +286,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
411      s->chr = chr;
412      s->irq = irq;
413      if (chr) {
414 -        qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
415 -                              mcf_uart_event, s);
416 +        qemu_chr_add_handlers(chr, &mcf_uart_handlers, s);
417      }
418      mcf_uart_reset(s);
419      return s;
420 diff --git a/hw/milkymist-uart.c b/hw/milkymist-uart.c
421 index 291fe3c..2dcb41c 100644
422 --- a/hw/milkymist-uart.c
423 +++ b/hw/milkymist-uart.c
424 @@ -189,6 +189,12 @@ static void milkymist_uart_reset(DeviceState *d)
425      s->regs[R_STAT] = STAT_THRE;
426  }
427  
428 +static const QemuChrHandlers uart_handlers = {
429 +    .fd_can_read = uart_can_rx,
430 +    .fd_read = uart_rx,
431 +    .fd_event = uart_event,
432 +};
433 +
434  static int milkymist_uart_init(SysBusDevice *dev)
435  {
436      MilkymistUartState *s = FROM_SYSBUS(typeof(*s), dev);
437 @@ -201,7 +207,7 @@ static int milkymist_uart_init(SysBusDevice *dev)
438  
439      s->chr = qemu_char_get_next_serial();
440      if (s->chr) {
441 -        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
442 +        qemu_chr_add_handlers(s->chr, &uart_handlers, s);
443      }
444  
445      return 0;
446 diff --git a/hw/pl011.c b/hw/pl011.c
447 index 3245702..0d620f8 100644
448 --- a/hw/pl011.c
449 +++ b/hw/pl011.c
450 @@ -258,6 +258,12 @@ static const VMStateDescription vmstate_pl011 = {
451      }
452  };
453  
454 +static const QemuChrHandlers pl011_handlers = {
455 +    .fd_can_read = pl011_can_receive,
456 +    .fd_read = pl011_receive,
457 +    .fd_event = pl011_event,
458 +};
459 +
460  static int pl011_init(SysBusDevice *dev, const unsigned char *id)
461  {
462      pl011_state *s = FROM_SYSBUS(pl011_state, dev);
463 @@ -273,8 +279,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
464      s->cr = 0x300;
465      s->flags = 0x90;
466      if (s->chr) {
467 -        qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
468 -                              pl011_event, s);
469 +        qemu_chr_add_handlers(s->chr, &pl011_handlers, s);
470      }
471      vmstate_register(&dev->qdev, -1, &vmstate_pl011, s);
472      return 0;
473 diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
474 index d5f1420..0b308cf 100644
475 --- a/hw/pxa2xx.c
476 +++ b/hw/pxa2xx.c
477 @@ -1962,6 +1962,12 @@ static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id)
478      return 0;
479  }
480  
481 +static const QemuChrHandlers pxa2xx_handlers = {
482 +    .fd_can_read = pxa2xx_fir_is_empty,
483 +    .fd_read = pxa2xx_fir_rx,
484 +    .fd_event = pxa2xx_fir_event,
485 +};
486 +
487  static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem,
488                  target_phys_addr_t base,
489                  qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma,
490 @@ -1980,10 +1986,9 @@ static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem,
491      memory_region_init_io(&s->iomem, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000);
492      memory_region_add_subregion(sysmem, base, &s->iomem);
493  
494 -    if (chr)
495 -        qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
496 -                        pxa2xx_fir_rx, pxa2xx_fir_event, s);
497 -
498 +    if (chr) {
499 +        qemu_chr_add_handlers(chr, &pxa2xx_handlers, s);
500 +    }
501      register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
502                      pxa2xx_fir_load, s);
503  
504 diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
505 index 8aca0d4..677c665 100644
506 --- a/hw/qdev-properties.c
507 +++ b/hw/qdev-properties.c
508 @@ -549,7 +549,7 @@ static void release_chr(Object *obj, const char *name, void *opaque)
509      CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
510  
511      if (*ptr) {
512 -        qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
513 +        qemu_chr_add_handlers(*ptr, NULL, NULL);
514      }
515  }
516  
517 diff --git a/hw/serial.c b/hw/serial.c
518 index a421d1e..056d823 100644
519 --- a/hw/serial.c
520 +++ b/hw/serial.c
521 @@ -736,6 +736,12 @@ static void serial_reset(void *opaque)
522      qemu_irq_lower(s->irq);
523  }
524  
525 +static const QemuChrHandlers serial_handlers = {
526 +    .fd_can_read = serial_can_receive1,
527 +    .fd_read = serial_receive1,
528 +    .fd_event = serial_event,
529 +};
530 +
531  static void serial_init_core(SerialState *s)
532  {
533      if (!s->chr) {
534 @@ -750,8 +756,7 @@ static void serial_init_core(SerialState *s)
535  
536      qemu_register_reset(serial_reset, s);
537  
538 -    qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
539 -                          serial_event, s);
540 +    qemu_chr_add_handlers(s->chr, &serial_handlers, s);
541  }
542  
543  /* Change the main reference oscillator frequency. */
544 diff --git a/hw/sh_serial.c b/hw/sh_serial.c
545 index 1d1883d..ce1c765 100644
546 --- a/hw/sh_serial.c
547 +++ b/hw/sh_serial.c
548 @@ -352,6 +352,12 @@ static const MemoryRegionOps sh_serial_ops = {
549      .endianness = DEVICE_NATIVE_ENDIAN,
550  };
551  
552 +static const QemuChrHandlers sh_serial_handlers = {
553 +    .fd_can_read = sh_serial_can_receive1,
554 +    .fd_read = sh_serial_receive1,
555 +    .fd_event = sh_serial_event,
556 +};
557 +
558  void sh_serial_init(MemoryRegion *sysmem,
559                      target_phys_addr_t base, int feat,
560                      uint32_t freq, CharDriverState *chr,
561 @@ -396,9 +402,9 @@ void sh_serial_init(MemoryRegion *sysmem,
562  
563      s->chr = chr;
564  
565 -    if (chr)
566 -        qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
567 -                             sh_serial_event, s);
568 +    if (chr) {
569 +        qemu_chr_add_handlers(chr, &sh_serial_handlers, s);
570 +    }
571  
572      s->eri = eri_source;
573      s->rxi = rxi_source;
574 diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
575 index 5da17a3..6c2ada1 100644
576 --- a/hw/spapr_vty.c
577 +++ b/hw/spapr_vty.c
578 @@ -54,6 +54,11 @@ void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
579      qemu_chr_fe_write(dev->chardev, buf, len);
580  }
581  
582 +static const QemuChrHandlers vty_handlers = {
583 +    .fd_can_read = vty_can_receive,
584 +    .fd_read = vty_receive,
585 +};
586 +
587  static int spapr_vty_init(VIOsPAPRDevice *sdev)
588  {
589      VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
590 @@ -63,8 +68,7 @@ static int spapr_vty_init(VIOsPAPRDevice *sdev)
591          exit(1);
592      }
593  
594 -    qemu_chr_add_handlers(dev->chardev, vty_can_receive,
595 -                          vty_receive, NULL, dev);
596 +    qemu_chr_add_handlers(dev->chardev, &vty_handlers, dev);
597  
598      return 0;
599  }
600 diff --git a/hw/strongarm.c b/hw/strongarm.c
601 index 7150eeb..594cf31 100644
602 --- a/hw/strongarm.c
603 +++ b/hw/strongarm.c
604 @@ -1199,6 +1199,12 @@ static const MemoryRegionOps strongarm_uart_ops = {
605      .endianness = DEVICE_NATIVE_ENDIAN,
606  };
607  
608 +static const QemuChrHandlers strongarm_uart_handlers = {
609 +    .fd_can_read = strongarm_uart_can_receive,
610 +    .fd_read = strongarm_uart_receive,
611 +    .fd_event = strongarm_uart_event,
612 +};
613 +
614  static int strongarm_uart_init(SysBusDevice *dev)
615  {
616      StrongARMUARTState *s = FROM_SYSBUS(StrongARMUARTState, dev);
617 @@ -1211,11 +1217,7 @@ static int strongarm_uart_init(SysBusDevice *dev)
618      s->tx_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_tx, s);
619  
620      if (s->chr) {
621 -        qemu_chr_add_handlers(s->chr,
622 -                        strongarm_uart_can_receive,
623 -                        strongarm_uart_receive,
624 -                        strongarm_uart_event,
625 -                        s);
626 +        qemu_chr_add_handlers(s->chr, &strongarm_uart_handlers, s);
627      }
628  
629      return 0;
630 diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
631 index 69b6e48..0ddfab6 100644
632 --- a/hw/usb/dev-serial.c
633 +++ b/hw/usb/dev-serial.c
634 @@ -475,6 +475,12 @@ static void usb_serial_event(void *opaque, int event)
635      }
636  }
637  
638 +static const QemuChrHandlers usb_serial_handlers = {
639 +    .fd_can_read = usb_serial_can_read,
640 +    .fd_read = usb_serial_read,
641 +    .fd_event = usb_serial_event,
642 +};
643 +
644  static int usb_serial_initfn(USBDevice *dev)
645  {
646      USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
647 @@ -487,8 +493,7 @@ static int usb_serial_initfn(USBDevice *dev)
648          return -1;
649      }
650  
651 -    qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
652 -                          usb_serial_event, s);
653 +    qemu_chr_add_handlers(s->cs, &usb_serial_handlers, s);
654      usb_serial_handle_reset(dev);
655      return 0;
656  }
657 diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
658 index ab8d79a..8b22c80 100644
659 --- a/hw/usb/redirect.c
660 +++ b/hw/usb/redirect.c
661 @@ -867,6 +867,12 @@ static void usbredir_chardev_event(void *opaque, int event)
662      }
663  }
664  
665 +static const QemuChrHandlers usbredir_chr_handlers = {
666 +    .fd_can_read = usbredir_chardev_can_read,
667 +    .fd_read = usbredir_chardev_read,
668 +    .fd_event = usbredir_chardev_event,
669 +};
670 +
671  /*
672   * init + destroy
673   */
674 @@ -905,8 +911,7 @@ static int usbredir_initfn(USBDevice *udev)
675  
676      /* Let the backend know we are ready */
677      qemu_chr_fe_open(dev->cs);
678 -    qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
679 -                          usbredir_chardev_read, usbredir_chardev_event, dev);
680 +    qemu_chr_add_handlers(dev->cs, &usbredir_chr_handlers, dev);
681  
682      add_boot_device_path(dev->bootindex, &udev->qdev, NULL);
683      return 0;
684 diff --git a/hw/virtio-console.c b/hw/virtio-console.c
685 index cffee3d..066590c 100644
686 --- a/hw/virtio-console.c
687 +++ b/hw/virtio-console.c
688 @@ -106,6 +106,12 @@ static void chr_event(void *opaque, int event)
689      }
690  }
691  
692 +static const QemuChrHandlers chr_handlers = {
693 +    .fd_can_read = chr_can_read,
694 +    .fd_read = chr_read,
695 +    .fd_event = chr_event,
696 +};
697 +
698  static int virtconsole_initfn(VirtIOSerialPort *port)
699  {
700      VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
701 @@ -117,8 +123,7 @@ static int virtconsole_initfn(VirtIOSerialPort *port)
702      }
703  
704      if (vcon->chr) {
705 -        qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
706 -                              vcon);
707 +        qemu_chr_add_handlers(vcon->chr, &chr_handlers, vcon);
708      }
709  
710      return 0;
711 diff --git a/hw/xen_console.c b/hw/xen_console.c
712 index 9426d73..e9fcadc 100644
713 --- a/hw/xen_console.c
714 +++ b/hw/xen_console.c
715 @@ -211,6 +211,11 @@ out:
716      return ret;
717  }
718  
719 +static const QemuChrHandlers xencons_handlers = {
720 +    .fd_can_read = xencons_can_receive,
721 +    .fd_read = xencons_receive,
722 +};
723 +
724  static int con_initialise(struct XenDevice *xendev)
725  {
726      struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
727 @@ -231,9 +236,9 @@ static int con_initialise(struct XenDevice *xendev)
728         return -1;
729  
730      xen_be_bind_evtchn(&con->xendev);
731 -    if (con->chr)
732 -        qemu_chr_add_handlers(con->chr, xencons_can_receive, xencons_receive,
733 -                              NULL, con);
734 +    if (con->chr) {
735 +        qemu_chr_add_handlers(con->chr, &xencons_handlers, con);
736 +    }
737  
738      xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
739                   con->ring_ref,
740 @@ -250,8 +255,9 @@ static void con_disconnect(struct XenDevice *xendev)
741      if (!xendev->dev) {
742          return;
743      }
744 -    if (con->chr)
745 -        qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
746 +    if (con->chr) {
747 +        qemu_chr_add_handlers(con->chr, NULL, NULL);
748 +    }
749      xen_be_unbind_evtchn(&con->xendev);
750  
751      if (con->sring) {
752 diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
753 index d0f32db..33f0cd5 100644
754 --- a/hw/xilinx_uartlite.c
755 +++ b/hw/xilinx_uartlite.c
756 @@ -195,6 +195,12 @@ static void uart_event(void *opaque, int event)
757  
758  }
759  
760 +static const QemuChrHandlers uart_handlers = {
761 +    .fd_can_read = uart_can_rx,
762 +    .fd_read = uart_rx,
763 +    .fd_event = uart_event,
764 +};
765 +
766  static int xilinx_uartlite_init(SysBusDevice *dev)
767  {
768      struct xlx_uartlite *s = FROM_SYSBUS(typeof (*s), dev);
769 @@ -207,8 +213,9 @@ static int xilinx_uartlite_init(SysBusDevice *dev)
770      sysbus_init_mmio(dev, &s->mmio);
771  
772      s->chr = qemu_char_get_next_serial();
773 -    if (s->chr)
774 -        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
775 +    if (s->chr) {
776 +        qemu_chr_add_handlers(s->chr, &uart_handlers, s);
777 +    }
778      return 0;
779  }
780  
781 diff --git a/monitor.c b/monitor.c
782 index f45cf92..99eee98 100644
783 --- a/monitor.c
784 +++ b/monitor.c
785 @@ -4942,6 +4942,18 @@ static void sortcmdlist(void)
786   * End:
787   */
788  
789 +static const QemuChrHandlers monitor_handlers = {
790 +    .fd_can_read = monitor_can_read,
791 +    .fd_read = monitor_read,
792 +    .fd_event = monitor_event,
793 +};
794 +
795 +static const QemuChrHandlers monitor_control_handlers = {
796 +    .fd_can_read = monitor_can_read,
797 +    .fd_read = monitor_control_read,
798 +    .fd_event = monitor_control_event,
799 +};
800 +
801  void monitor_init(CharDriverState *chr, int flags)
802  {
803      static int is_first_init = 1;
804 @@ -4965,14 +4977,12 @@ void monitor_init(CharDriverState *chr, int flags)
805      if (monitor_ctrl_mode(mon)) {
806          mon->mc = g_malloc0(sizeof(MonitorControl));
807          /* Control mode requires special handlers */
808 -        qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read,
809 -                              monitor_control_event, mon);
810 +        qemu_chr_add_handlers(chr, &monitor_control_handlers, mon);
811          qemu_chr_fe_set_echo(chr, true);
812  
813          json_message_parser_init(&mon->mc->parser, handle_qmp_command);
814      } else {
815 -        qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
816 -                              monitor_event, mon);
817 +        qemu_chr_add_handlers(chr, &monitor_handlers, mon);
818      }
819  
820      QLIST_INSERT_HEAD(&mon_list, mon, entry);
821 diff --git a/net/slirp.c b/net/slirp.c
822 index 8db66ea..63542cb 100644
823 --- a/net/slirp.c
824 +++ b/net/slirp.c
825 @@ -593,6 +593,11 @@ static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
826      slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size);
827  }
828  
829 +static const QemuChrHandlers guestfwd_handlers = {
830 +    .fd_can_read = guestfwd_can_read,
831 +    .fd_read = guestfwd_read,
832 +};
833 +
834  static int slirp_guestfwd(SlirpState *s, const char *config_str,
835                            int legacy_format)
836  {
837 @@ -658,8 +663,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
838          fwd->port = port;
839          fwd->slirp = s->slirp;
840  
841 -        qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
842 -                              NULL, fwd);
843 +        qemu_chr_add_handlers(fwd->hd, &guestfwd_handlers, fwd);
844      }
845      return 0;
846  
847 diff --git a/qemu-char.c b/qemu-char.c
848 index a1fdf88..bd443db 100644
849 --- a/qemu-char.c
850 +++ b/qemu-char.c
851 @@ -192,19 +192,26 @@ void qemu_chr_fe_printf(CharDriverState *s, const char *fmt, ...)
852      va_end(ap);
853  }
854  
855 +static const QemuChrHandlers null_handlers = {
856 +    /* All handlers are initialised to NULL */
857 +};
858 +
859  void qemu_chr_add_handlers(CharDriverState *s,
860 -                           IOCanReadHandler *fd_can_read,
861 -                           IOReadHandler *fd_read,
862 -                           IOEventHandler *fd_event,
863 -                           void *opaque)
864 +                           const QemuChrHandlers *handlers, void *opaque)
865  {
866 -    if (!opaque && !fd_can_read && !fd_read && !fd_event) {
867 +    if (!s) {
868 +        return;
869 +    }
870 +    if (!opaque && !handlers) {
871          /* chr driver being released. */
872          ++s->avail_connections;
873      }
874 -    s->chr_can_read = fd_can_read;
875 -    s->chr_read = fd_read;
876 -    s->chr_event = fd_event;
877 +    if (!handlers) {
878 +        handlers = &null_handlers;
879 +    }
880 +    s->chr_can_read = handlers->fd_can_read;
881 +    s->chr_read = handlers->fd_read;
882 +    s->chr_event = handlers->fd_event;
883      s->handler_opaque = opaque;
884      if (s->chr_update_read_handler)
885          s->chr_update_read_handler(s);
886 @@ -442,6 +449,12 @@ static void mux_chr_event(void *opaque, int event)
887          mux_chr_send_event(d, i, event);
888  }
889  
890 +static const QemuChrHandlers mux_chr_handlers = {
891 +    .fd_can_read = mux_chr_can_read,
892 +    .fd_read = mux_chr_read,
893 +    .fd_event = mux_chr_event,
894 +};
895 +
896  static void mux_chr_update_read_handler(CharDriverState *chr)
897  {
898      MuxDriver *d = chr->opaque;
899 @@ -456,8 +469,7 @@ static void mux_chr_update_read_handler(CharDriverState *chr)
900      d->chr_event[d->mux_cnt] = chr->chr_event;
901      /* Fix up the real driver with mux routines */
902      if (d->mux_cnt == 0) {
903 -        qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read,
904 -                              mux_chr_event, chr);
905 +        qemu_chr_add_handlers(d->drv, &mux_chr_handlers, chr);
906      }
907      if (d->focus != -1) {
908          mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
909 diff --git a/qemu-char.h b/qemu-char.h
910 index 486644b..dfa8c2d 100644
911 --- a/qemu-char.h
912 +++ b/qemu-char.h
913 @@ -222,10 +222,15 @@ void qemu_chr_be_write(CharDriverState *s, uint8_t *buf, int len);
914   */
915  void qemu_chr_be_event(CharDriverState *s, int event);
916  
917 -void qemu_chr_add_handlers(CharDriverState *s,
918 -                           IOCanReadHandler *fd_can_read,
919 -                           IOReadHandler *fd_read,
920 -                           IOEventHandler *fd_event,
921 +
922 +typedef struct QemuChrHandlers {
923 +    IOCanReadHandler *fd_can_read;
924 +    IOReadHandler *fd_read;
925 +    IOHandler *fd_write_unblocked;
926 +    IOEventHandler *fd_event;
927 +} QemuChrHandlers;
928 +
929 +void qemu_chr_add_handlers(CharDriverState *s, const QemuChrHandlers *handlers,
930                             void *opaque);
931  
932  void qemu_chr_generic_open(CharDriverState *s);
933 diff --git a/qtest.c b/qtest.c
934 index fbfab4e..4ab5b69 100644
935 --- a/qtest.c
936 +++ b/qtest.c
937 @@ -416,6 +416,13 @@ static void qtest_event(void *opaque, int event)
938      }
939  }
940  
941 +static const QemuChrHandlers test_handlers = {
942 +    .fd_can_read = qtest_can_read,
943 +    .fd_read = qtest_read,
944 +    .fd_event = qtest_event,
945 +};
946 +
947 +
948  int qtest_init(void)
949  {
950      CharDriverState *chr;
951 @@ -425,7 +432,7 @@ int qtest_init(void)
952      configure_icount("0");
953      chr = qemu_chr_new("qtest", qtest_chrdev, NULL);
954  
955 -    qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr);
956 +    qemu_chr_add_handlers(chr, &test_handlers, chr);
957      qemu_chr_fe_set_echo(chr, true);
958  
959      inbuf = g_string_new("");
960 -- 
961 1.7.12.1
962