a5bd9f6
From 1e5b1dd686ca089f9b4034ec26541e7515c9fa58 Mon Sep 17 00:00:00 2001
a5bd9f6
From: Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
a5bd9f6
Date: Sun, 20 Jan 2013 22:45:53 +0100
a5bd9f6
Subject: [PATCH 119/364] 	Split long USB transfers into short ones.
a5bd9f6
a5bd9f6
---
a5bd9f6
 ChangeLog                    |  4 ++++
a5bd9f6
 grub-core/bus/usb/usbtrans.c | 20 ++++++++++++++++----
a5bd9f6
 include/grub/usbtrans.h      |  2 ++
a5bd9f6
 3 files changed, 22 insertions(+), 4 deletions(-)
a5bd9f6
a5bd9f6
diff --git a/ChangeLog b/ChangeLog
a5bd9f6
index 4d09825..c8edf73 100644
a5bd9f6
--- a/ChangeLog
a5bd9f6
+++ b/ChangeLog
a5bd9f6
@@ -1,3 +1,7 @@
a5bd9f6
+2013-01-20  AleŇ° Nesrsta  <starous@volny.cz>
a5bd9f6
+
a5bd9f6
+	Split long USB transfers into short ones.
a5bd9f6
+
a5bd9f6
 2013-01-20  Andrey Borzenkov <arvidjaar@gmail.com>
a5bd9f6
 
a5bd9f6
 	* docs/grub.texi (Simple configuration): Clarify GRUB_HIDDEN_TIMEOUT
a5bd9f6
diff --git a/grub-core/bus/usb/usbtrans.c b/grub-core/bus/usb/usbtrans.c
a5bd9f6
index 167fae5..154c72d 100644
a5bd9f6
--- a/grub-core/bus/usb/usbtrans.c
a5bd9f6
+++ b/grub-core/bus/usb/usbtrans.c
a5bd9f6
@@ -351,11 +351,23 @@ grub_usb_err_t
a5bd9f6
 grub_usb_bulk_read (grub_usb_device_t dev,
a5bd9f6
 		    int endpoint, grub_size_t size, char *data)
a5bd9f6
 {
a5bd9f6
-  grub_size_t actual;
a5bd9f6
+  grub_size_t actual, transferred;
a5bd9f6
   grub_usb_err_t err;
a5bd9f6
-  err = grub_usb_bulk_readwrite (dev, endpoint, size, data,
a5bd9f6
-				 GRUB_USB_TRANSFER_TYPE_IN, 1000, &actual);
a5bd9f6
-  if (!err && actual != size)
a5bd9f6
+  grub_size_t current_size, position;
a5bd9f6
+
a5bd9f6
+  for (position = 0, transferred = 0;
a5bd9f6
+       position < size; position += MAX_USB_TRANSFER_LEN)
a5bd9f6
+    {
a5bd9f6
+      current_size = size - position;
a5bd9f6
+      if (current_size >= MAX_USB_TRANSFER_LEN)
a5bd9f6
+	current_size = MAX_USB_TRANSFER_LEN;
a5bd9f6
+      err = grub_usb_bulk_readwrite (dev, endpoint, current_size,
a5bd9f6
+              &data[position], GRUB_USB_TRANSFER_TYPE_IN, 1000, &actual);
a5bd9f6
+      transferred += actual;
a5bd9f6
+      if (err || (current_size != actual) ) break;
a5bd9f6
+    }
a5bd9f6
+
a5bd9f6
+  if (!err && transferred != size)
a5bd9f6
     err = GRUB_USB_ERR_DATA;
a5bd9f6
   return err;
a5bd9f6
 }
a5bd9f6
diff --git a/include/grub/usbtrans.h b/include/grub/usbtrans.h
a5bd9f6
index 5ee276d..5429007 100644
a5bd9f6
--- a/include/grub/usbtrans.h
a5bd9f6
+++ b/include/grub/usbtrans.h
a5bd9f6
@@ -19,6 +19,8 @@
a5bd9f6
 #ifndef	GRUB_USBTRANS_H
a5bd9f6
 #define	GRUB_USBTRANS_H	1
a5bd9f6
 
a5bd9f6
+#define MAX_USB_TRANSFER_LEN 0x0800
a5bd9f6
+
a5bd9f6
 typedef enum
a5bd9f6
   {
a5bd9f6
     GRUB_USB_TRANSFER_TYPE_IN,
a5bd9f6
-- 
a5bd9f6
1.8.1.4
a5bd9f6