From 61b122324a196a34ce8119f884be6dfd27ae5b59 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Wed, 29 Feb 2012 12:39:28 +0100
Subject: [PATCH 13/35] usb-redir: Add flow control support

RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1330519171-24231-14-git-send-email-kraxel@redhat.com>
Patchwork-id: 37772
O-Subject: [RHEL-6.3 qemu-kvm PATCH v2 13/16] usb-redir: Add flow control support
Bugzilla: 758104
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Markus Armbruster <armbru@redhat.com>
RH-Acked-by: Alex Williamson <alex.williamson@redhat.com>

From: Hans de Goede <hdegoede@redhat.com>

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 usb-redir.c |   26 ++++++++++++++++++++++++--
 1 files changed, 24 insertions(+), 2 deletions(-)

Signed-off-by: Michal Novotny <minovotn@redhat.com>
---
 usb-redir.c |   26 ++++++++++++++++++++++++--
 1 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/usb-redir.c b/usb-redir.c
index 434499e..7985bbe 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -228,12 +228,22 @@ static int usbredir_read(void *priv, uint8_t *data, int count)
 static int usbredir_write(void *priv, uint8_t *data, int count)
 {
     USBRedirDevice *dev = priv;
+    int r;
 
-    if (!dev->cs->opened) {
+    if (!dev->cs->opened || dev->cs->write_blocked) {
         return 0;
     }
 
-    return qemu_chr_write(dev->cs, data, count);
+    r = qemu_chr_write(dev->cs, data, count);
+
+    if (r < 0) {
+        if (dev->cs->write_blocked) {
+            return 0;
+        }
+        return -1;
+    }
+
+    return r;
 }
 
 /*
@@ -862,6 +872,17 @@ static void usbredir_chardev_event(void *opaque, int event)
     }
 }
 
+static void usbredir_chardev_write_unblocked(void *opaque)
+{
+    USBRedirDevice *dev = opaque;
+
+    if (dev->parser == NULL) {
+        /* usbredir_open_close_bh hasn't handled the open event yet */
+        return;
+    }
+    usbredirparser_do_write(dev->parser);
+}
+
 /*
  * init + destroy
  */
@@ -870,6 +891,7 @@ static QemuChrHandlers usbredir_handlers = {
     .fd_can_read = usbredir_chardev_can_read,
     .fd_read = usbredir_chardev_read,
     .fd_event = usbredir_chardev_event,
+    .fd_write_unblocked = usbredir_chardev_write_unblocked,
 };
 
 static int usbredir_initfn(USBDevice *udev)
-- 
1.7.7.6

