From patchwork Tue Sep 29 12:04:48 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [6/6] vnc: Add a virtio-console-bus device to send / receive guest clipboard Date: Tue, 29 Sep 2009 02:04:48 -0000 From: Amit Shah X-Patchwork-Id: 34423 Message-Id: <1254225888-17093-7-git-send-email-amit.shah@redhat.com> To: qemu-devel@nongnu.org Cc: Amit Shah This is a simple device on the virtio-console-bus that syncs with the guest for clipboard activity. A daemon is needed in the guest to send / receive the clipboard data. This patch is just meant to show how to use the read/write api is exposed for devices that ride on top of the virtio-console-bus. Signed-off-by: Amit Shah --- vnc.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 67 insertions(+), 0 deletions(-) diff --git a/vnc.c b/vnc.c index ff2d4a8..b6f9cce 100644 --- a/vnc.c +++ b/vnc.c @@ -29,6 +29,7 @@ #include "qemu_socket.h" #include "qemu-timer.h" #include "acl.h" +#include "hw/virtio-console.h" #define VNC_REFRESH_INTERVAL_BASE 30 #define VNC_REFRESH_INTERVAL_INC 50 @@ -44,6 +45,11 @@ } \ } +typedef struct VirtConVnc { + VirtConPort port; +} VirtConVnc; + +static VirtConVnc *virtcon_vnc; static VncDisplay *vnc_display; /* needed for info vnc */ static DisplayChangeListener *dcl; @@ -659,6 +665,34 @@ static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h) } } +static size_t vnc_clipboard_data_from_guest(VirtConPort *port, + const uint8_t *buf, size_t len) +{ + VncState *vs; + VncDisplay *vd; + DisplayState *ds; + + if (!is_vnc_active()) + return 0; + + ds = vnc_display->ds; + vd = ds->opaque; + + for (vs = vd->clients; vs; vs = vs->next) { + vnc_write_u8(vs, 3); /* ServerCutText */ + vnc_write_u8(vs, 0); /* Padding */ + vnc_write_u8(vs, 0); /* Padding */ + vnc_write_u8(vs, 0); /* Padding */ + vnc_write_u32(vs, len); + while (len--) { + vnc_write_u8(vs, *(buf++)); + } + vnc_flush(vs); + } + return len; +} + + static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h) { /* send bitblit op to the vnc client */ @@ -1240,6 +1274,7 @@ uint32_t read_u32(uint8_t *data, size_t offset) static void client_cut_text(VncState *vs, size_t len, uint8_t *text) { + virtio_console_write(&virtcon_vnc->port, text, len); } static void check_pointer_type_change(VncState *vs, int absolute) @@ -2197,6 +2232,10 @@ static void vnc_connect(VncDisplay *vd, int csock) vnc_init_timer(vd); + if (virtcon_vnc) { + virtio_console_open(&virtcon_vnc->port); + } + /* vs might be free()ed here */ } @@ -2516,3 +2555,31 @@ int vnc_display_open(DisplayState *ds, const char *display) } return qemu_set_fd_handler2(vs->lsock, NULL, vnc_listen_read, NULL, vs); } + +static int vcon_vnc_initfn(VirtConDevice *dev) +{ + VirtConPort *port; + VirtConVnc *vnc; + + port = DO_UPCAST(VirtConPort, dev, &dev->qdev); + vnc = DO_UPCAST(VirtConVnc, port, port); + virtcon_vnc = vnc; + + port->name = qemu_strdup("org.qemu.clipboard"); + /* We don't want to keep old data lingering if vnc is not connected */ + port->flush_buffers = 1; + return 0; +} + +static VirtConPortInfo virtcon_vnc_info = { + .qdev.name = "virtconvnc", + .qdev.size = sizeof(VirtConVnc), + .init = vcon_vnc_initfn, + .have_data = vnc_clipboard_data_from_guest, +}; + +static void virtcon_port_register(void) +{ + virtcon_port_qdev_register(&virtcon_vnc_info); +} +device_init(virtcon_port_register)