aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-09-15 17:18:06 -0700
committerPeter Maydell <peter.maydell@linaro.org>2014-09-16 22:46:16 +0100
commit49d41c1a0b223eace0bdc0596438de84bc20af05 (patch)
tree41ae2e71c273ea89f4fd41b0e6ba6474a4d9c9ed
parentc02f327dc9fedaf6276c43c3d582d57f697a188e (diff)
virtserial ping-pong deviceranchu-virtserial
Version of the android pipe pingpong test backend using virtserial
-rw-r--r--hw/char/Makefile.objs1
-rw-r--r--hw/char/virtio-pingpong.c115
2 files changed, 116 insertions, 0 deletions
diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs
index 317385d26f..7170aeff40 100644
--- a/hw/char/Makefile.objs
+++ b/hw/char/Makefile.objs
@@ -5,6 +5,7 @@ common-obj-$(CONFIG_PL011) += pl011.o
common-obj-$(CONFIG_SERIAL) += serial.o serial-isa.o
common-obj-$(CONFIG_SERIAL_PCI) += serial-pci.o
common-obj-$(CONFIG_VIRTIO) += virtio-console.o
+common-obj-$(CONFIG_VIRTIO) += virtio-pingpong.o
common-obj-$(CONFIG_XILINX) += xilinx_uartlite.o
common-obj-$(CONFIG_XEN_BACKEND) += xen_console.o
common-obj-$(CONFIG_CADENCE) += cadence_uart.o
diff --git a/hw/char/virtio-pingpong.c b/hw/char/virtio-pingpong.c
new file mode 100644
index 0000000000..db299215e7
--- /dev/null
+++ b/hw/char/virtio-pingpong.c
@@ -0,0 +1,115 @@
+/* virtio-pingpong: virtio-serial backend that just sends all
+ * data it receives back to the guest.
+ *
+ * Copyright (c) 2013 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ */
+
+#include "sysemu/char.h"
+#include "qemu/error-report.h"
+#include "trace.h"
+#include "hw/virtio/virtio-serial.h"
+
+#define TYPE_VIRTIO_PINGPONG "virtpingpong"
+#define VIRTIO_PINGPONG(obj) \
+ OBJECT_CHECK(VirtPingpong, (obj), TYPE_VIRTIO_PINGPONG)
+
+typedef struct VirtPingpong {
+ VirtIOSerialPort parent_obj;
+ /* Any per-backend data goes here */
+} VirtPingpong;
+
+
+/* Callback function that's called when the guest sends us data */
+static ssize_t virtpingpong_have_data(VirtIOSerialPort *port,
+ const uint8_t *buf, ssize_t len)
+{
+ VirtPingpong *vpp = VIRTIO_PINGPONG(port);
+ ssize_t ret;
+
+ printf("virtpingpong_have_data: %ld bytes\n", len);
+
+ ret = virtio_serial_write(port, buf, len);
+
+ printf("virtpingpong_have_data: passed %ld bytes back\n", ret);
+
+ if (ret < len) {
+ /* We didn't manage to send all the data: throttle the
+ * port so we don't get any more for now.
+ */
+ virtio_serial_throttle_port(port, true);
+ }
+
+ return ret;
+}
+
+static void virtpingpong_guest_writable(VirtIOSerialPort *port)
+{
+ printf("virtpingpong_guest_writable\n");
+ /* Just unthrottle the other end of the port so it can send us more data */
+ virtio_serial_throttle_port(port, false);
+}
+
+/* Callback function that's called when the guest opens/closes the port */
+static void virtpingpong_set_guest_connected(VirtIOSerialPort *port,
+ int guest_connected)
+{
+ VirtPingpong *vpp = VIRTIO_PINGPONG(port);
+
+ printf("virtpingpong: guest %sconnected\n", guest_connected ? "" : "dis");
+}
+
+static void virtpingpong_realize(DeviceState *dev, Error **errp)
+{
+ VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
+ VirtPingpong *vpp = VIRTIO_PINGPONG(dev);
+ VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(dev);
+
+ if (port->id == 0 && !k->is_console) {
+ error_setg(errp, "Port number 0 on virtio-serial devices reserved "
+ "for virtconsole devices for backward compatibility.");
+ return;
+ }
+
+ /* The host end of this connection is always open. */
+ virtio_serial_open(port);
+}
+
+static void virtpingpong_unrealize(DeviceState *dev, Error **errp)
+{
+ VirtPingpong *vpp = VIRTIO_PINGPONG(dev);
+
+ /* Nothing for us to do here */
+}
+
+static void virtpingpong_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
+
+ k->realize = virtpingpong_realize;
+ k->unrealize = virtpingpong_unrealize;
+ k->have_data = virtpingpong_have_data;
+ k->guest_writable = virtpingpong_guest_writable;
+ k->set_guest_connected = virtpingpong_set_guest_connected;
+ /* If we have any device state for save/load we should
+ * register a vmstate here.
+ */
+}
+
+static const TypeInfo virtpingpong_info = {
+ .name = TYPE_VIRTIO_PINGPONG,
+ .parent = TYPE_VIRTIO_SERIAL_PORT,
+ .instance_size = sizeof(VirtPingpong),
+ .class_init = virtpingpong_class_init,
+};
+
+static void virtpingpong_register_types(void)
+{
+ type_register_static(&virtpingpong_info);
+}
+
+type_init(virtpingpong_register_types)