- Timestamp:
- Apr 30, 2016, 11:29:25 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
rtos_arduino/trunk/arduino_lib/hardware/arduino/samd/cores/arduino/USB/CDC.cpp
r136 r224 1 /* Copyright (c) 2011, Peter Barrett 2 ** 3 ** Permission to use, copy, modify, and/or distribute this software for 4 ** any purpose with or without fee is hereby granted, provided that the 5 ** above copyright notice and this permission notice appear in all copies. 6 ** 7 ** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 8 ** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 9 ** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 10 ** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES 11 ** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 12 ** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 13 ** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 14 ** SOFTWARE. 1 /* 2 Copyright (c) 2015 Arduino LLC. All right reserved. 3 4 This library is free software; you can redistribute it and/or 5 modify it under the terms of the GNU Lesser General Public 6 License as published by the Free Software Foundation; either 7 version 2.1 of the License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 See the GNU Lesser General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public 15 License along with this library; if not, write to the Free Software 16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 /* 19 ** Modified 04/04/2016 by Arduino.org development team 15 20 */ 16 21 … … 20 25 21 26 // Include Atmel headers 22 #include "Arduino.h" 23 #include "sam.h" 24 #include "wiring_constants.h" 25 #include "USBCore.h" 26 #include "USB/USB_device.h" 27 #include "USBDesc.h" 28 #include "USBAPI.h" 29 30 #include "Reset.h" 31 27 #include <Arduino.h> 28 #include <Reset.h> 32 29 33 30 #ifdef CDC_ENABLED 34 31 35 #define CDC_SERIAL_BUFFER_SIZE 6432 #define CDC_SERIAL_BUFFER_SIZE 256 36 33 37 34 /* For information purpose only since RTS is not always handled by the terminal application */ … … 41 38 #define CDC_LINESTATE_READY (CDC_LINESTATE_RTS | CDC_LINESTATE_DTR) 42 39 43 struct ring_buffer 44 { 40 struct ring_buffer { 45 41 uint8_t buffer[CDC_SERIAL_BUFFER_SIZE]; 46 42 volatile uint32_t head; 47 43 volatile uint32_t tail; 44 volatile bool full; 48 45 }; 49 50 ring_buffer cdc_rx_buffer = { { 0 }, 0, 0}; 51 52 typedef struct 53 { 54 uint32_t dwDTERate; 55 uint8_t bCharFormat; 56 uint8_t bParityType; 57 uint8_t bDataBits; 58 uint8_t lineState; 46 ring_buffer cdc_rx_buffer = {{0}, 0, 0, false}; 47 48 typedef struct { 49 uint32_t dwDTERate; 50 uint8_t bCharFormat; 51 uint8_t bParityType; 52 uint8_t bDataBits; 53 uint8_t lineState; 59 54 } LineInfo; 60 55 61 56 _Pragma("pack(1)") 62 static volatile LineInfo _usbLineInfo = { 63 64 0x00,// bCharFormat65 0x00,// bParityType66 0x08,// bDataBits67 0x00// lineState57 static volatile LineInfo _usbLineInfo = { 58 115200, // dWDTERate 59 0x00, // bCharFormat 60 0x00, // bParityType 61 0x08, // bDataBits 62 0x00 // lineState 68 63 }; 69 64 70 static const CDCDescriptor _cdcInterface =71 { 72 #if (defined CDC_ENABLED) && defined(HID_ENABLED) 65 static volatile int32_t breakValue = -1; 66 67 static CDCDescriptor _cdcInterface = { 73 68 D_IAD(0, 2, CDC_COMMUNICATION_INTERFACE_CLASS, CDC_ABSTRACT_CONTROL_MODEL, 0), 74 #endif 75 // 76 D_INTERFACE(CDC_ACM_INTERFACE, 1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0),77 D_CDCCS( CDC_HEADER, CDC_V1_10 & 0xFF, (CDC_V1_10>>8) & 0x0FF ),// Header (1.10 bcd)78 79 D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT, 6),// SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported80 D_CDCCS(CDC_UNION, CDC_ACM_INTERFACE,CDC_DATA_INTERFACE),// Communication interface is master, data interface is slave 081 D_CDCCS(CDC_CALL_MANAGEMENT, 1,1),// Device handles call management (not)82 D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10, 0x10),83 84 // 85 D_INTERFACE(CDC_DATA_INTERFACE, 2,CDC_DATA_INTERFACE_CLASS,0,0),86 D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT), USB_ENDPOINT_TYPE_BULK,EPX_SIZE,0),87 D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ), USB_ENDPOINT_TYPE_BULK,EPX_SIZE,0)69 70 // CDC communication interface 71 D_INTERFACE(CDC_ACM_INTERFACE, 1, CDC_COMMUNICATION_INTERFACE_CLASS, CDC_ABSTRACT_CONTROL_MODEL, 0), 72 D_CDCCS(CDC_HEADER, CDC_V1_10 & 0xFF, (CDC_V1_10>>8) & 0x0FF), // Header (1.10 bcd) 73 74 D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT, 6), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported 75 D_CDCCS(CDC_UNION, CDC_ACM_INTERFACE, CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0 76 D_CDCCS(CDC_CALL_MANAGEMENT, 1, 1), // Device handles call management (not) 77 D_ENDPOINT(USB_ENDPOINT_IN(CDC_ENDPOINT_ACM), USB_ENDPOINT_TYPE_INTERRUPT, 0x10, 0x10), 78 79 // CDC data interface 80 D_INTERFACE(CDC_DATA_INTERFACE, 2, CDC_DATA_INTERFACE_CLASS, 0, 0), 81 D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT), USB_ENDPOINT_TYPE_BULK, EPX_SIZE, 0), 82 D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ), USB_ENDPOINT_TYPE_BULK, EPX_SIZE, 0) 88 83 }; 89 84 _Pragma("pack()") 90 85 91 const void* WEAK CDC_GetInterface(void) 92 { 93 return &_cdcInterface; 94 } 95 96 uint32_t WEAK CDC_GetInterfaceLength(void) 97 { 98 return sizeof( _cdcInterface ); 99 } 100 101 bool WEAK CDC_Setup(Setup& setup) 102 { 103 uint8_t r = setup.bRequest; 104 uint8_t requestType = setup.bmRequestType; 86 const void* _CDC_GetInterface(void) 87 { 88 return &_cdcInterface; 89 } 90 91 uint32_t _CDC_GetInterfaceLength(void) 92 { 93 return sizeof(_cdcInterface); 94 } 95 96 int CDC_GetInterface(uint8_t* interfaceNum) 97 { 98 interfaceNum[0] += 2; // uses 2 99 return USBD_SendControl(&_cdcInterface,sizeof(_cdcInterface)); 100 } 101 102 bool CDC_Setup(Setup& pSetup) 103 { 104 uint8_t requestType = pSetup.bmRequestType; 105 uint8_t r = pSetup.bRequest; 105 106 106 107 if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) … … 108 109 if (CDC_GET_LINE_CODING == r) 109 110 { 110 USBD_SendControl( 0,(void*)&_usbLineInfo,7);111 USBD_SendControl((void*)&_usbLineInfo, 7); 111 112 return true; 112 113 } … … 117 118 if (CDC_SET_LINE_CODING == r) 118 119 { 119 while( UDD_FifoByteCount(EP0) <15); 120 //USBD_RecvControl((void*)&_usbLineInfo,7); 121 uint8_t* line = (uint8_t*)&_usbLineInfo; 122 for(uint8_t i = 0; i<7; i++) 123 line[i] = setup.data[i]; 124 return false; 120 USBD_RecvControl((void*)&_usbLineInfo, 7); 125 121 } 126 122 127 123 if (CDC_SET_CONTROL_LINE_STATE == r) 128 124 { 129 _usbLineInfo.lineState = setup.wValueL; 125 _usbLineInfo.lineState = pSetup.wValueL; 126 } 127 128 if (r == CDC_SET_LINE_CODING || r == CDC_SET_CONTROL_LINE_STATE) 129 { 130 130 // auto-reset into the bootloader is triggered when the port, already 131 // open at 1200 bps, is closed. 132 if (1200 == _usbLineInfo.dwDTERate) 131 // open at 1200 bps, is closed. We check DTR state to determine if host 132 // port is open (bit 0 of lineState). 133 if (_usbLineInfo.dwDTERate == 1200 && (_usbLineInfo.lineState & 0x01) == 0) 133 134 { 134 // We check DTR state to determine if host port is open (bit 0 of lineState).135 if ((_usbLineInfo.lineState & 0x01) == 0)136 initiateReset(250);137 else138 135 initiateReset(250); 136 } 137 else 138 { 139 cancelReset(); 139 140 } 140 141 return false; 141 142 } 143 144 if (r == CDC_SEND_BREAK) 145 { 146 breakValue = ((uint16_t)pSetup.wValueH << 8) | pSetup.wValueL; 147 return false; 148 } 142 149 } 143 150 return false; … … 159 166 void Serial_::accept(void) 160 167 { 168 uint8_t buffer[CDC_SERIAL_BUFFER_SIZE]; 169 uint32_t len = USBD_Recv(CDC_ENDPOINT_OUT, &buffer, CDC_SERIAL_BUFFER_SIZE); 170 171 uint8_t enableInterrupts = ((__get_PRIMASK() & 0x1) == 0); 172 __disable_irq(); 173 174 ring_buffer *ringBuffer = &cdc_rx_buffer; 175 uint32_t i = ringBuffer->head; 176 177 uint32_t k = 0; 178 while (len > 0 && !ringBuffer->full) { 179 len--; 180 ringBuffer->buffer[i++] = buffer[k++]; 181 i %= CDC_SERIAL_BUFFER_SIZE; 182 if (i == ringBuffer->tail) 183 ringBuffer->full = true; 184 } 185 ringBuffer->head = i; 186 if (enableInterrupts) { 187 __enable_irq(); 188 } 189 } 190 191 int Serial_::available(void) 192 { 161 193 ring_buffer *buffer = &cdc_rx_buffer; 162 uint32_t i = (uint32_t)(buffer->head+1) % CDC_SERIAL_BUFFER_SIZE; 163 164 // if we should be storing the received character into the location 165 // just before the tail (meaning that the head would advance to the 166 // current location of the tail), we're about to overflow the buffer 167 // and so we don't write the character or advance the head. 168 while (i != buffer->tail) { 169 uint32_t c; 170 if (!USBD_Available(CDC_ENDPOINT_OUT)) { 171 UDD_ReleaseRX(CDC_ENDPOINT_OUT); 172 break; 173 } 174 c = USBD_Recv(CDC_ENDPOINT_OUT); 175 buffer->buffer[buffer->head] = c; 176 buffer->head = i; 177 178 i = (i + 1) % CDC_SERIAL_BUFFER_SIZE; 179 } 180 } 181 182 int Serial_::available(void) 194 if (buffer->full) { 195 return CDC_SERIAL_BUFFER_SIZE; 196 } 197 if (buffer->head == buffer->tail) { 198 USB->DEVICE.DeviceEndpoint[CDC_ENDPOINT_OUT].EPINTENSET.reg = USB_DEVICE_EPINTENCLR_TRCPT(1); 199 } 200 return (uint32_t)(CDC_SERIAL_BUFFER_SIZE + buffer->head - buffer->tail) % CDC_SERIAL_BUFFER_SIZE; 201 } 202 203 int Serial_::peek(void) 183 204 { 184 205 ring_buffer *buffer = &cdc_rx_buffer; 185 return (uint32_t)(CDC_SERIAL_BUFFER_SIZE + buffer->head - buffer->tail) % CDC_SERIAL_BUFFER_SIZE; 186 } 187 188 int Serial_::peek(void) 206 if (buffer->head == buffer->tail && !buffer->full) { 207 return -1; 208 } else { 209 return buffer->buffer[buffer->tail]; 210 } 211 } 212 213 214 // if the ringBuffer is empty: try to fill it 215 // if it's still empty: return -1 216 // else return the last char 217 // so the buffer is filled only when needed 218 int Serial_::read(void) 189 219 { 190 220 ring_buffer *buffer = &cdc_rx_buffer; 191 221 192 if (buffer->head == buffer->tail)193 {194 return -1;195 }196 else197 {198 return buffer->buffer[buffer->tail];199 }200 }201 202 int Serial_::read(void)203 {204 ring_buffer *buffer = &cdc_rx_buffer;205 206 222 // if the head isn't ahead of the tail, we don't have any characters 207 if (buffer->head == buffer->tail) 223 if (buffer->head == buffer->tail && !buffer->full) 224 { 225 if (USBD_Available(CDC_ENDPOINT_OUT)) 226 accept(); 227 } 228 if (buffer->head == buffer->tail && !buffer->full) 208 229 { 209 230 return -1; … … 213 234 unsigned char c = buffer->buffer[buffer->tail]; 214 235 buffer->tail = (uint32_t)(buffer->tail + 1) % CDC_SERIAL_BUFFER_SIZE; 215 if (USBD_Available(CDC_ENDPOINT_OUT)) 216 accept(); 236 buffer->full = false; 217 237 return c; 218 238 } … … 231 251 bytes sent before the user opens the connection or after 232 252 the connection is closed are lost - just like with a UART. */ 233 253 if (_usbLineInfo.lineState > 0) // Problem with Windows(R) 234 254 { 235 255 uint32_t r = USBD_Send(CDC_ENDPOINT_IN, buffer, size); 236 256 237 if (r > 0) 238 { 257 if (r == 0) { 239 258 return r; 240 } else 241 { 259 } else { 242 260 setWriteError(); 243 261 return 0; 244 262 } 245 }263 } 246 264 setWriteError(); 247 265 return 0; … … 259 277 // We add a short delay before returning to fix a bug observed by Federico 260 278 // where the port is configured (lineState != 0) but not quite opened. 261 262 279 Serial_::operator bool() 263 280 { … … 277 294 } 278 295 279 Serial_ SerialUSB; 296 int32_t Serial_::readBreak() { 297 uint8_t enableInterrupts = ((__get_PRIMASK() & 0x1) == 0); 298 299 // disable interrupts, 300 // to avoid clearing a breakValue that might occur 301 // while processing the current break value 302 __disable_irq(); 303 304 int32_t ret = breakValue; 305 306 breakValue = -1; 307 308 if (enableInterrupts) { 309 // re-enable the interrupts 310 __enable_irq(); 311 } 312 313 return ret; 314 } 315 316 unsigned long Serial_::baud() { 317 return _usbLineInfo.dwDTERate; 318 } 319 320 uint8_t Serial_::stopbits() { 321 return _usbLineInfo.bCharFormat; 322 } 323 324 uint8_t Serial_::paritytype() { 325 return _usbLineInfo.bParityType; 326 } 327 328 uint8_t Serial_::numbits() { 329 return _usbLineInfo.bDataBits; 330 } 331 332 bool Serial_::dtr() { 333 return _usbLineInfo.lineState & 0x1; 334 } 335 336 bool Serial_::rts() { 337 return _usbLineInfo.lineState & 0x2; 338 } 339 340 Serial_ SerialUSB(USBDevice); 280 341 281 342 #endif
Note:
See TracChangeset
for help on using the changeset viewer.