Fork of Smoothie to port to mbed non-LPC targets.
Fork of Smoothie by
USBSerial.cpp
00001 /* Copyright (c) 2010-2011 mbed.org, MIT License 00002 * 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00004 * and associated documentation files (the "Software"), to deal in the Software without 00005 * restriction, including without limitation the rights to use, copy, modify, merge, publish, 00006 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 00007 * Software is furnished to do so, subject to the following conditions: 00008 * 00009 * The above copyright notice and this permission notice shall be included in all copies or 00010 * substantial portions of the Software. 00011 * 00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00017 */ 00018 00019 #include <cstdint> 00020 #include <cstdio> 00021 00022 #include "USBSerial.h" 00023 00024 #include "libs/Kernel.h" 00025 #include "libs/SerialMessage.h" 00026 00027 // extern void setled(int, bool); 00028 #define setled(a, b) do {} while (0) 00029 00030 #define iprintf(...) do { } while (0) 00031 00032 USBSerial::USBSerial(USB *u): USBCDC(u), rxbuf(256 + 8), txbuf(128 + 8) 00033 { 00034 usb = u; 00035 nl_in_rx = 0; 00036 attach = attached = false; 00037 flush_to_nl = false; 00038 } 00039 00040 void USBSerial::ensure_tx_space(int space) 00041 { 00042 while (txbuf.free() < space) 00043 { 00044 usb->endpointSetInterrupt(CDC_BulkIn.bEndpointAddress, true); 00045 usb->usbisr(); 00046 } 00047 } 00048 00049 int USBSerial::_putc(int c) 00050 { 00051 if (!attached) 00052 return 1; 00053 ensure_tx_space(1); 00054 txbuf.queue(c); 00055 00056 usb->endpointSetInterrupt(CDC_BulkIn.bEndpointAddress, true); 00057 return 1; 00058 } 00059 00060 int USBSerial::_getc() 00061 { 00062 if (!attached) 00063 return 0; 00064 uint8_t c = 0; 00065 setled(4, 1); while (rxbuf.isEmpty()); setled(4, 0); 00066 rxbuf.dequeue(&c); 00067 if (rxbuf.free() == MAX_PACKET_SIZE_EPBULK) 00068 { 00069 usb->endpointSetInterrupt(CDC_BulkOut.bEndpointAddress, true); 00070 iprintf("rxbuf has room for another packet, interrupt enabled\n"); 00071 } 00072 else if ((rxbuf.free() < MAX_PACKET_SIZE_EPBULK) && (nl_in_rx == 0)) 00073 { 00074 // handle potential deadlock where a short line, and the beginning of a very long line are bundled in one usb packet 00075 rxbuf.flush(); 00076 flush_to_nl = true; 00077 00078 usb->endpointSetInterrupt(CDC_BulkOut.bEndpointAddress, true); 00079 iprintf("rxbuf has room for another packet, interrupt enabled\n"); 00080 } 00081 if (nl_in_rx > 0) 00082 if (c == '\n' || c == '\r') 00083 nl_in_rx--; 00084 00085 return c; 00086 } 00087 00088 int USBSerial::puts(const char *str) 00089 { 00090 if (!attached) 00091 return strlen(str); 00092 int i = 0; 00093 while (*str) 00094 { 00095 ensure_tx_space(1); 00096 txbuf.queue(*str); 00097 if ((txbuf.available() % 64) == 0) 00098 usb->endpointSetInterrupt(CDC_BulkIn.bEndpointAddress, true); 00099 i++; 00100 str++; 00101 } 00102 usb->endpointSetInterrupt(CDC_BulkIn.bEndpointAddress, true); 00103 return i; 00104 } 00105 00106 uint16_t USBSerial::writeBlock(const uint8_t * buf, uint16_t size) 00107 { 00108 if (!attached) 00109 return size; 00110 if (size > txbuf.free()) 00111 { 00112 size = txbuf.free(); 00113 } 00114 if (size > 0) 00115 { 00116 for (uint8_t i = 0; i < size; i++) 00117 { 00118 txbuf.queue(buf[i]); 00119 } 00120 usb->endpointSetInterrupt(CDC_BulkIn.bEndpointAddress, true); 00121 } 00122 return size; 00123 } 00124 00125 bool USBSerial::USBEvent_EPIn(uint8_t bEP, uint8_t bEPStatus) 00126 { 00127 /* 00128 * Called in ISR context 00129 */ 00130 00131 // static bool needToSendNull = false; 00132 00133 bool r = true; 00134 00135 if (bEP != CDC_BulkIn.bEndpointAddress) 00136 return false; 00137 00138 iprintf("USBSerial:EpIn: 0x%02X\n", bEPStatus); 00139 00140 uint8_t b[MAX_PACKET_SIZE_EPBULK]; 00141 00142 int l = txbuf.available(); 00143 iprintf("%d bytes queued\n", l); 00144 if (l > 0) 00145 { 00146 if (l > MAX_PACKET_SIZE_EPBULK) 00147 l = MAX_PACKET_SIZE_EPBULK; 00148 iprintf("Sending %d bytes:\n\t", l); 00149 int i; 00150 for (i = 0; i < l; i++) { 00151 txbuf.dequeue(&b[i]); 00152 if (b[i] >= 32 && b[i] < 128) 00153 iprintf("%c", b[i]); 00154 else { 00155 iprintf("\\x%02X", b[i]); 00156 } 00157 } 00158 iprintf("\nSending...\n"); 00159 send(b, l); 00160 iprintf("Sent\n"); 00161 if (txbuf.available() == 0) 00162 r = false; 00163 } 00164 else 00165 { 00166 r = false; 00167 } 00168 iprintf("USBSerial:EpIn Complete\n"); 00169 return r; 00170 } 00171 00172 bool USBSerial::USBEvent_EPOut(uint8_t bEP, uint8_t bEPStatus) 00173 { 00174 /* 00175 * Called in ISR context 00176 */ 00177 00178 bool r = true; 00179 00180 iprintf("USBSerial:EpOut\n"); 00181 if (bEP != CDC_BulkOut.bEndpointAddress) 00182 return false; 00183 00184 if (rxbuf.free() < MAX_PACKET_SIZE_EPBULK) 00185 { 00186 // usb->endpointSetInterrupt(bEP, false); 00187 return false; 00188 } 00189 00190 uint8_t c[MAX_PACKET_SIZE_EPBULK]; 00191 uint32_t size = 64; 00192 00193 //we read the packet received and put it on the circular buffer 00194 readEP(c, &size); 00195 iprintf("Read %ld bytes:\n\t", size); 00196 for (uint8_t i = 0; i < size; i++) { 00197 00198 if (flush_to_nl == false) 00199 rxbuf.queue(c[i]); 00200 00201 if (c[i] >= 32 && c[i] < 128) 00202 { 00203 iprintf("%c", c[i]); 00204 } 00205 else 00206 { 00207 iprintf("\\x%02X", c[i]); 00208 } 00209 00210 if (c[i] == '\n' || c[i] == '\r') 00211 { 00212 if (flush_to_nl) 00213 flush_to_nl = false; 00214 else 00215 nl_in_rx++; 00216 } 00217 else if (rxbuf.isFull() && (nl_in_rx == 0)) 00218 { 00219 // to avoid a deadlock with very long lines, we must dump the buffer 00220 // and continue flushing to the next newline 00221 rxbuf.flush(); 00222 flush_to_nl = true; 00223 } 00224 } 00225 iprintf("\nQueued, %d empty\n", rxbuf.free()); 00226 00227 if (rxbuf.free() < MAX_PACKET_SIZE_EPBULK) 00228 { 00229 // if buffer is full, stall endpoint, do not accept more data 00230 r = false; 00231 00232 if (nl_in_rx == 0) 00233 { 00234 // we have to check for long line deadlock here too 00235 flush_to_nl = true; 00236 rxbuf.flush(); 00237 00238 // and since our buffer is empty, we can accept more data 00239 r = true; 00240 } 00241 } 00242 00243 usb->readStart(CDC_BulkOut.bEndpointAddress, MAX_PACKET_SIZE_EPBULK); 00244 iprintf("USBSerial:EpOut Complete\n"); 00245 return r; 00246 } 00247 00248 uint8_t USBSerial::available() 00249 { 00250 return rxbuf.available(); 00251 } 00252 00253 void USBSerial::on_module_loaded() 00254 { 00255 this->register_for_event(ON_MAIN_LOOP); 00256 } 00257 00258 void USBSerial::on_main_loop(void *argument) 00259 { 00260 // apparently some OSes don't assert DTR when a program opens the port 00261 if (available() && !attach) 00262 attach = true; 00263 00264 if (attach != attached) 00265 { 00266 if (attach) 00267 { 00268 attached = true; 00269 THEKERNEL->streams->append_stream(this); 00270 writeBlock((const uint8_t *) "Smoothie\nok\n", 12); 00271 } 00272 else 00273 { 00274 attached = false; 00275 THEKERNEL->streams->remove_stream(this); 00276 txbuf.flush(); 00277 rxbuf.flush(); 00278 nl_in_rx = 0; 00279 } 00280 } 00281 if (nl_in_rx) 00282 { 00283 string received; 00284 while (available()) 00285 { 00286 char c = _getc(); 00287 if( c == '\n' || c == '\r') 00288 { 00289 struct SerialMessage message; 00290 message.message = received; 00291 message.stream = this; 00292 iprintf("USBSerial Received: %s\n", message.message.c_str()); 00293 THEKERNEL->call_event(ON_CONSOLE_LINE_RECEIVED, &message ); 00294 return; 00295 } 00296 else 00297 { 00298 received += c; 00299 } 00300 } 00301 } 00302 } 00303 00304 void USBSerial::on_attach() 00305 { 00306 attach = true; 00307 } 00308 00309 void USBSerial::on_detach() 00310 { 00311 attach = false; 00312 }
Generated on Tue Jul 12 2022 20:09:03 by 1.7.2