From f3e78a4a2920665b45b964049db3ebed9b8f1dc7 Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@bug.st>
Date: Sat, 24 May 2014 00:13:07 +0200
Subject: Backported Print class from ide-1.5.x branch

Close #1951
---
 cores/arduino/Print.cpp | 8 ++------
 cores/arduino/Print.h   | 3 +++
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/cores/arduino/Print.cpp b/cores/arduino/Print.cpp
index 53961ec..5df5630 100755
--- a/cores/arduino/Print.cpp
+++ b/cores/arduino/Print.cpp
@@ -41,7 +41,7 @@ size_t Print::write(const uint8_t *buffer, size_t size)
 
 size_t Print::print(const __FlashStringHelper *ifsh)
 {
-  const char PROGMEM *p = (const char PROGMEM *)ifsh;
+  PGM_P p = reinterpret_cast<PGM_P>(ifsh);
   size_t n = 0;
   while (1) {
     unsigned char c = pgm_read_byte(p++);
@@ -53,11 +53,7 @@ size_t Print::print(const __FlashStringHelper *ifsh)
 
 size_t Print::print(const String &s)
 {
-  size_t n = 0;
-  for (uint16_t i = 0; i < s.length(); i++) {
-    n += write(s[i]);
-  }
-  return n;
+  return write(s.c_str(), s.length());
 }
 
 size_t Print::print(const char str[])
diff --git a/cores/arduino/Print.h b/cores/arduino/Print.h
index dc76150..7b53aa4 100755
--- a/cores/arduino/Print.h
+++ b/cores/arduino/Print.h
@@ -51,6 +51,9 @@ class Print
       return write((const uint8_t *)str, strlen(str));
     }
     virtual size_t write(const uint8_t *buffer, size_t size);
+    size_t write(const char *buffer, size_t size) {
+      return write((const uint8_t *)buffer, size);
+    }
     
     size_t print(const __FlashStringHelper *);
     size_t print(const String &);
-- 
cgit v1.2.3-18-g5258


From 872c88bb5f643702edcc8d0ebfc1f6cd13bcf414 Mon Sep 17 00:00:00 2001
From: Justin Rajewski <justin@embeddedmicro.com>
Date: Tue, 18 Mar 2014 14:15:41 -0700
Subject: improved USB write speeds

---
 cores/arduino/CDC.cpp  | 7 ++++++-
 cores/arduino/USBAPI.h | 1 +
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/cores/arduino/CDC.cpp b/cores/arduino/CDC.cpp
index e1e859d..fb0c0e0 100644
--- a/cores/arduino/CDC.cpp
+++ b/cores/arduino/CDC.cpp
@@ -199,6 +199,11 @@ void Serial_::flush(void)
 }
 
 size_t Serial_::write(uint8_t c)
+{
+	return write(&c, 1);
+}
+
+size_t Serial_::write(const uint8_t *buffer, size_t size)
 {
 	/* only try to send bytes if the high-level CDC connection itself 
 	 is open (not just the pipe) - the OS should set lineState when the port
@@ -210,7 +215,7 @@ size_t Serial_::write(uint8_t c)
 	// 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)	{
-		int r = USB_Send(CDC_TX,&c,1);
+		int r = USB_Send(CDC_TX,buffer,size);
 		if (r > 0) {
 			return r;
 		} else {
diff --git a/cores/arduino/USBAPI.h b/cores/arduino/USBAPI.h
index 7a14285..1c5ecf0 100644
--- a/cores/arduino/USBAPI.h
+++ b/cores/arduino/USBAPI.h
@@ -40,6 +40,7 @@ public:
 	virtual int read(void);
 	virtual void flush(void);
 	virtual size_t write(uint8_t);
+	virtual size_t write(const uint8_t*, size_t);
 	using Print::write; // pull in write(str) and write(buf, size) from Print
 	operator bool();
 };
-- 
cgit v1.2.3-18-g5258


From b57b2ae3c163a855efca331bf817d566e328f88b Mon Sep 17 00:00:00 2001
From: Paul Brook <paul@nowt.org>
Date: Thu, 20 Mar 2014 22:44:41 +0000
Subject: Fix race condition in USB CDC transmit

If the Start of Frame interrupt triggers just after the call
to USB_SendSpace in USB_Send then we can get data loss.
When the first bank is full and the second partially full,
the SOF handler will release the second bank via USB_Flush.
Data is then lost due to overflow as USB_Send continues writing data
to the now-closed bank.

Fix this by re-checking the FIFO status inside LockEP, immediately before
doing the data write.

Signed-off-by: Paul Brook <paul@nowt.org>
---
 cores/arduino/USBCore.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/cores/arduino/USBCore.cpp b/cores/arduino/USBCore.cpp
index d3e0170..76ceb01 100644
--- a/cores/arduino/USBCore.cpp
+++ b/cores/arduino/USBCore.cpp
@@ -290,9 +290,12 @@ int USB_Send(u8 ep, const void* d, int len)
 
 		if (n > len)
 			n = len;
-		len -= n;
 		{
 			LockEP lock(ep);
+			// Frame may have been released by the SOF interrupt handler
+			if (!ReadWriteAllowed())
+				continue;
+			len -= n;
 			if (ep & TRANSFER_ZERO)
 			{
 				while (n--)
-- 
cgit v1.2.3-18-g5258


From 5962f155f70a5c67d14280d1b178f5197fb00df4 Mon Sep 17 00:00:00 2001
From: Paul Brook <paul@nowt.org>
Date: Fri, 21 Mar 2014 18:43:19 +0000
Subject: Improve CDC read code

Read CDC data from USB FIFO on demand instead of in ISR.
Remove superfluous ring buffer.

Signed-off-by: Paul Brook <paul@nowt.org>
---
 cores/arduino/CDC.cpp     | 66 +++++++++--------------------------------------
 cores/arduino/USBAPI.h    |  3 +--
 cores/arduino/USBCore.cpp |  2 --
 3 files changed, 13 insertions(+), 58 deletions(-)

diff --git a/cores/arduino/CDC.cpp b/cores/arduino/CDC.cpp
index fb0c0e0..3dbf15d 100644
--- a/cores/arduino/CDC.cpp
+++ b/cores/arduino/CDC.cpp
@@ -23,21 +23,6 @@
 #if defined(USBCON)
 #ifdef CDC_ENABLED
 
-#if (RAMEND < 1000)
-#define SERIAL_BUFFER_SIZE 16
-#else
-#define SERIAL_BUFFER_SIZE 64
-#endif
-
-struct ring_buffer
-{
-	unsigned char buffer[SERIAL_BUFFER_SIZE];
-	volatile int head;
-	volatile int tail;
-};
-
-ring_buffer cdc_rx_buffer = { { 0 }, 0, 0};
-
 typedef struct
 {
 	u32	dwDTERate;
@@ -129,7 +114,6 @@ bool WEAK CDC_Setup(Setup& setup)
 }
 
 
-int _serialPeek = -1;
 void Serial_::begin(unsigned long baud_count)
 {
 }
@@ -142,55 +126,29 @@ void Serial_::end(void)
 {
 }
 
-void Serial_::accept(void) 
-{
-	ring_buffer *buffer = &cdc_rx_buffer;
-	int i = (unsigned int)(buffer->head+1) % SERIAL_BUFFER_SIZE;
-	
-	// if we should be storing the received character into the location
-	// just before the tail (meaning that the head would advance to the
-	// current location of the tail), we're about to overflow the buffer
-	// and so we don't write the character or advance the head.
-
-	// while we have room to store a byte
-	while (i != buffer->tail) {
-		int c = USB_Recv(CDC_RX);
-		if (c == -1)
-			break;	// no more data
-		buffer->buffer[buffer->head] = c;
-		buffer->head = i;
-
-		i = (unsigned int)(buffer->head+1) % SERIAL_BUFFER_SIZE;
-	}
-}
-
 int Serial_::available(void)
 {
-	ring_buffer *buffer = &cdc_rx_buffer;
-	return (unsigned int)(SERIAL_BUFFER_SIZE + buffer->head - buffer->tail) % SERIAL_BUFFER_SIZE;
+	if (peek_buffer >= 0) {
+		return 1;
+	}
+	return USB_Available(CDC_RX);
 }
 
 int Serial_::peek(void)
 {
-	ring_buffer *buffer = &cdc_rx_buffer;
-	if (buffer->head == buffer->tail) {
-		return -1;
-	} else {
-		return buffer->buffer[buffer->tail];
-	}
+	if (peek_buffer < 0)
+		peek_buffer = USB_Recv(CDC_RX);
+	return peek_buffer;
 }
 
 int Serial_::read(void)
 {
-	ring_buffer *buffer = &cdc_rx_buffer;
-	// if the head isn't ahead of the tail, we don't have any characters
-	if (buffer->head == buffer->tail) {
-		return -1;
-	} else {
-		unsigned char c = buffer->buffer[buffer->tail];
-		buffer->tail = (unsigned int)(buffer->tail + 1) % SERIAL_BUFFER_SIZE;
+	if (peek_buffer >= 0) {
+		int c = peek_buffer;
+		peek_buffer = -1;
 		return c;
-	}	
+	}
+	return USB_Recv(CDC_RX);
 }
 
 void Serial_::flush(void)
diff --git a/cores/arduino/USBAPI.h b/cores/arduino/USBAPI.h
index 1c5ecf0..d506b58 100644
--- a/cores/arduino/USBAPI.h
+++ b/cores/arduino/USBAPI.h
@@ -28,14 +28,13 @@ extern USBDevice_ USBDevice;
 class Serial_ : public Stream
 {
 private:
-	ring_buffer *_cdc_rx_buffer;
+	int peek_buffer;
 public:
 	void begin(unsigned long);
 	void begin(unsigned long, uint8_t);
 	void end(void);
 
 	virtual int available(void);
-	virtual void accept(void);
 	virtual int peek(void);
 	virtual int read(void);
 	virtual void flush(void);
diff --git a/cores/arduino/USBCore.cpp b/cores/arduino/USBCore.cpp
index 76ceb01..f8123e5 100644
--- a/cores/arduino/USBCore.cpp
+++ b/cores/arduino/USBCore.cpp
@@ -614,8 +614,6 @@ ISR(USB_GEN_vect)
 	{
 #ifdef CDC_ENABLED
 		USB_Flush(CDC_TX);				// Send a tx frame if found
-		if (USB_Available(CDC_RX))	// Handle received bytes (if any)
-			Serial.accept();
 #endif
 		
 		// check whether the one-shot period has elapsed.  if so, turn off the LED
-- 
cgit v1.2.3-18-g5258