Allow TABS in config
[clinton/Smoothieware.git] / src / libs / USBDevice / USBSerial / USBSerial.cpp
index 28ec811..f01c151 100644 (file)
 \r
 #include "libs/Kernel.h"\r
 #include "libs/SerialMessage.h"\r
+#include "StreamOutputPool.h"\r
 \r
 // extern void setled(int, bool);\r
 #define setled(a, b) do {} while (0)\r
 \r
 #define iprintf(...) do { } while (0)\r
 \r
-USBSerial::USBSerial(USB *u): USBCDC(u), rxbuf(128 + 8), txbuf(128 + 8)\r
+USBSerial::USBSerial(USB *u): USBCDC(u), rxbuf(256 + 8), txbuf(128 + 8)\r
 {\r
     usb = u;\r
     nl_in_rx = 0;\r
     attach = attached = false;\r
+    flush_to_nl = false;\r
 }\r
 \r
 void USBSerial::ensure_tx_space(int space)\r
@@ -68,6 +70,15 @@ int USBSerial::_getc()
         usb->endpointSetInterrupt(CDC_BulkOut.bEndpointAddress, true);\r
         iprintf("rxbuf has room for another packet, interrupt enabled\n");\r
     }\r
+    else if ((rxbuf.free() < MAX_PACKET_SIZE_EPBULK) && (nl_in_rx == 0))\r
+    {\r
+        // handle potential deadlock where a short line, and the beginning of a very long line are bundled in one usb packet\r
+        rxbuf.flush();\r
+        flush_to_nl = true;\r
+\r
+        usb->endpointSetInterrupt(CDC_BulkOut.bEndpointAddress, true);\r
+        iprintf("rxbuf has room for another packet, interrupt enabled\n");\r
+    }\r
     if (nl_in_rx > 0)\r
         if (c == '\n' || c == '\r')\r
             nl_in_rx--;\r
@@ -184,7 +195,10 @@ bool USBSerial::USBEvent_EPOut(uint8_t bEP, uint8_t bEPStatus)
     readEP(c, &size);\r
     iprintf("Read %ld bytes:\n\t", size);\r
     for (uint8_t i = 0; i < size; i++) {\r
-        rxbuf.queue(c[i]);\r
+\r
+        if (flush_to_nl == false)\r
+            rxbuf.queue(c[i]);\r
+\r
         if (c[i] >= 32 && c[i] < 128)\r
         {\r
             iprintf("%c", c[i]);\r
@@ -193,14 +207,38 @@ bool USBSerial::USBEvent_EPOut(uint8_t bEP, uint8_t bEPStatus)
         {\r
             iprintf("\\x%02X", c[i]);\r
         }\r
+\r
         if (c[i] == '\n' || c[i] == '\r')\r
-            nl_in_rx++;\r
+        {\r
+            if (flush_to_nl)\r
+                flush_to_nl = false;\r
+            else\r
+                nl_in_rx++;\r
+        }\r
+        else if (rxbuf.isFull() && (nl_in_rx == 0))\r
+        {\r
+            // to avoid a deadlock with very long lines, we must dump the buffer\r
+            // and continue flushing to the next newline\r
+            rxbuf.flush();\r
+            flush_to_nl = true;\r
+        }\r
     }\r
     iprintf("\nQueued, %d empty\n", rxbuf.free());\r
 \r
     if (rxbuf.free() < MAX_PACKET_SIZE_EPBULK)\r
     {\r
+        // if buffer is full, stall endpoint, do not accept more data\r
         r = false;\r
+\r
+        if (nl_in_rx == 0)\r
+        {\r
+            // we have to check for long line deadlock here too\r
+            flush_to_nl = true;\r
+            rxbuf.flush();\r
+\r
+            // and since our buffer is empty, we can accept more data\r
+            r = true;\r
+        }\r
     }\r
 \r
     usb->readStart(CDC_BulkOut.bEndpointAddress, MAX_PACKET_SIZE_EPBULK);\r
@@ -229,13 +267,13 @@ void USBSerial::on_main_loop(void *argument)
         if (attach)\r
         {\r
             attached = true;\r
-            kernel->streams->append_stream(this);\r
+            THEKERNEL->streams->append_stream(this);\r
             writeBlock((const uint8_t *) "Smoothie\nok\n", 12);\r
         }\r
         else\r
         {\r
             attached = false;\r
-            kernel->streams->remove_stream(this);\r
+            THEKERNEL->streams->remove_stream(this);\r
             txbuf.flush();\r
             rxbuf.flush();\r
             nl_in_rx = 0;\r
@@ -253,7 +291,7 @@ void USBSerial::on_main_loop(void *argument)
                 message.message = received;\r
                 message.stream = this;\r
                 iprintf("USBSerial Received: %s\n", message.message.c_str());\r
-                this->kernel->call_event(ON_CONSOLE_LINE_RECEIVED, &message );\r
+                THEKERNEL->call_event(ON_CONSOLE_LINE_RECEIVED, &message );\r
                 return;\r
             }\r
             else\r