From ffd05f251a9c3b0c31661738a468bd994d328396 Mon Sep 17 00:00:00 2001
From: Jean-Christophe BUDA <jean-christophe.buda@atmel.com>
Date: Fri, 3 Jul 2015 12:12:46 +0200
Subject: [PATCH] Fix to USBDevice blocking-send

---
 cores/arduino/USB/CDC.cpp     |  4 +--
 cores/arduino/USB/USBCore.cpp | 61 ++++++++++++++++++++++++++++-------
 2 files changed, 51 insertions(+), 14 deletions(-)

diff --git a/cores/arduino/USB/CDC.cpp b/cores/arduino/USB/CDC.cpp
index 0ecee14a..f3e4cd70 100644
--- a/cores/arduino/USB/CDC.cpp
+++ b/cores/arduino/USB/CDC.cpp
@@ -242,11 +242,11 @@ size_t Serial_::write(const uint8_t *buffer, size_t size)
 	// TODO - ZE - check behavior on different OSes and test what happens if an
 	// open connection isn't broken cleanly (cable is yanked out, host dies
 	// or locks up, or host virtual serial port hangs)
-//	if (_usbLineInfo.lineState > 0)  // Problem with Windows(R)
+	if (_usbLineInfo.lineState > 0)  // Problem with Windows(R)
 	{
 		uint32_t r = usb.send(CDC_ENDPOINT_IN, buffer, size);
 
-		if (r > 0) {
+		if (r == 0) {
 			return r;
 		} else {
 			setWriteError();
diff --git a/cores/arduino/USB/USBCore.cpp b/cores/arduino/USB/USBCore.cpp
index 3852e30f..3792c85c 100644
--- a/cores/arduino/USB/USBCore.cpp
+++ b/cores/arduino/USB/USBCore.cpp
@@ -579,27 +579,64 @@ uint8_t USBDeviceClass::armRecv(uint32_t ep, uint32_t len)
 //	Blocking Send of data to an endpoint
 uint32_t USBDeviceClass::send(uint32_t ep, const void *data, uint32_t len)
 {
+	uint32_t length = 0;
+
 	if (!_usbConfiguration)
 		return -1;
+	if (len > 16384)
+		return -1;
 
-	//armSend(ep, data, len);
+	if ((unsigned int)data > 0x20000000)
+	{
+		// Buffer in RAM
+		usbd.epBank1SetAddress(ep, (void *)data);
+		usbd.epBank1SetMultiPacketSize(ep, 0);
 
-	/* memcopy could be safer in multithreaded environment */
-	memcpy(&udd_ep_in_cache_buffer[ep], data, len);
+		usbd.epBank1SetByteCount(ep, len);
 
-	usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]);
-	usbd.epBank1SetByteCount(ep, len);
+		// Clear the transfer complete flag
+		usbd.epBank1AckTransferComplete(ep);
 
-	// Clear the transfer complete flag
-	usbd.epBank1AckTransferComplete(ep);
+		// RAM buffer is full, we can send data (IN)
+		usbd.epBank1SetReady(ep);
 
-	// RAM buffer is full, we can send data (IN)
-	usbd.epBank1SetReady(ep);
+		// Wait for transfer to complete
+		while (!usbd.epBank1IsTransferComplete(ep)) {
+			;  // need fire exit.
+		}
+		len = 0;
+	}
+	else
+	{
+		// Flash area
+		while (len != 0)
+		{
+			if (len >= 64) {
+				length = 64;
+			} else {
+				length = len;
+			}
 
-	// Wait for transfer to complete
-	while (!usbd.epBank1IsTransferComplete(ep)) {
-		;  // need fire exit.
+			/* memcopy could be safer in multi threaded environment */
+			memcpy(&udd_ep_in_cache_buffer[ep], data, length);
+
+			usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]);
+			usbd.epBank1SetByteCount(ep, length);
+
+			// Clear the transfer complete flag
+			usbd.epBank1AckTransferComplete(ep);
+
+			// RAM buffer is full, we can send data (IN)
+			usbd.epBank1SetReady(ep);
+
+			// Wait for transfer to complete
+			while (!usbd.epBank1IsTransferComplete(ep)) {
+				;  // need fire exit.
+			}
+			len -= length;
+		}
 	}
+
 	return len;
 }
 
-- 
GitLab