source: rtos_arduino/trunk/arduino_lib/hardware/arduino/samd/cores/arduino/USB/CDC.cpp@ 224

Last change on this file since 224 was 224, checked in by ertl-honda, 8 years ago

1.7.10のファイルに更新

File size: 8.2 KB
Line 
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
20*/
21
22#include <stdlib.h>
23#include <stdio.h>
24#include <stdint.h>
25
26// Include Atmel headers
27#include <Arduino.h>
28#include <Reset.h>
29
30#ifdef CDC_ENABLED
31
32#define CDC_SERIAL_BUFFER_SIZE 256
33
34/* For information purpose only since RTS is not always handled by the terminal application */
35#define CDC_LINESTATE_DTR 0x01 // Data Terminal Ready
36#define CDC_LINESTATE_RTS 0x02 // Ready to Send
37
38#define CDC_LINESTATE_READY (CDC_LINESTATE_RTS | CDC_LINESTATE_DTR)
39
40struct ring_buffer {
41 uint8_t buffer[CDC_SERIAL_BUFFER_SIZE];
42 volatile uint32_t head;
43 volatile uint32_t tail;
44 volatile bool full;
45};
46ring_buffer cdc_rx_buffer = {{0}, 0, 0, false};
47
48typedef struct {
49 uint32_t dwDTERate;
50 uint8_t bCharFormat;
51 uint8_t bParityType;
52 uint8_t bDataBits;
53 uint8_t lineState;
54} LineInfo;
55
56_Pragma("pack(1)")
57static volatile LineInfo _usbLineInfo = {
58 115200, // dWDTERate
59 0x00, // bCharFormat
60 0x00, // bParityType
61 0x08, // bDataBits
62 0x00 // lineState
63};
64
65static volatile int32_t breakValue = -1;
66
67static CDCDescriptor _cdcInterface = {
68 D_IAD(0, 2, CDC_COMMUNICATION_INTERFACE_CLASS, CDC_ABSTRACT_CONTROL_MODEL, 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)
83};
84_Pragma("pack()")
85
86const void* _CDC_GetInterface(void)
87{
88 return &_cdcInterface;
89}
90
91uint32_t _CDC_GetInterfaceLength(void)
92{
93 return sizeof(_cdcInterface);
94}
95
96int CDC_GetInterface(uint8_t* interfaceNum)
97{
98 interfaceNum[0] += 2; // uses 2
99 return USBD_SendControl(&_cdcInterface,sizeof(_cdcInterface));
100}
101
102bool CDC_Setup(Setup& pSetup)
103{
104 uint8_t requestType = pSetup.bmRequestType;
105 uint8_t r = pSetup.bRequest;
106
107 if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
108 {
109 if (CDC_GET_LINE_CODING == r)
110 {
111 USBD_SendControl((void*)&_usbLineInfo, 7);
112 return true;
113 }
114 }
115
116 if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
117 {
118 if (CDC_SET_LINE_CODING == r)
119 {
120 USBD_RecvControl((void*)&_usbLineInfo, 7);
121 }
122
123 if (CDC_SET_CONTROL_LINE_STATE == r)
124 {
125 _usbLineInfo.lineState = pSetup.wValueL;
126 }
127
128 if (r == CDC_SET_LINE_CODING || r == CDC_SET_CONTROL_LINE_STATE)
129 {
130 // auto-reset into the bootloader is triggered when the port, already
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)
134 {
135 initiateReset(250);
136 }
137 else
138 {
139 cancelReset();
140 }
141 return false;
142 }
143
144 if (r == CDC_SEND_BREAK)
145 {
146 breakValue = ((uint16_t)pSetup.wValueH << 8) | pSetup.wValueL;
147 return false;
148 }
149 }
150 return false;
151}
152
153uint32_t _serialPeek = -1;
154void Serial_::begin(uint32_t baud_count)
155{
156}
157
158void Serial_::begin(uint32_t baud_count, uint8_t config)
159{
160}
161
162void Serial_::end(void)
163{
164}
165
166void Serial_::accept(void)
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
191int Serial_::available(void)
192{
193 ring_buffer *buffer = &cdc_rx_buffer;
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
203int Serial_::peek(void)
204{
205 ring_buffer *buffer = &cdc_rx_buffer;
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
218int Serial_::read(void)
219{
220 ring_buffer *buffer = &cdc_rx_buffer;
221
222 // if the head isn't ahead of the tail, we don't have any characters
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)
229 {
230 return -1;
231 }
232 else
233 {
234 unsigned char c = buffer->buffer[buffer->tail];
235 buffer->tail = (uint32_t)(buffer->tail + 1) % CDC_SERIAL_BUFFER_SIZE;
236 buffer->full = false;
237 return c;
238 }
239}
240
241void Serial_::flush(void)
242{
243 USBD_Flush(CDC_ENDPOINT_IN);
244}
245
246size_t Serial_::write(const uint8_t *buffer, size_t size)
247{
248 /* only try to send bytes if the high-level CDC connection itself
249 is open (not just the pipe) - the OS should set lineState when the port
250 is opened and clear lineState when the port is closed.
251 bytes sent before the user opens the connection or after
252 the connection is closed are lost - just like with a UART. */
253 if (_usbLineInfo.lineState > 0) // Problem with Windows(R)
254 {
255 uint32_t r = USBD_Send(CDC_ENDPOINT_IN, buffer, size);
256
257 if (r == 0) {
258 return r;
259 } else {
260 setWriteError();
261 return 0;
262 }
263 }
264 setWriteError();
265 return 0;
266}
267
268size_t Serial_::write(uint8_t c) {
269 return write(&c, 1);
270}
271
272// This operator is a convenient way for a sketch to check whether the
273// port has actually been configured and opened by the host (as opposed
274// to just being connected to the host). It can be used, for example, in
275// setup() before printing to ensure that an application on the host is
276// actually ready to receive and display the data.
277// We add a short delay before returning to fix a bug observed by Federico
278// where the port is configured (lineState != 0) but not quite opened.
279Serial_::operator bool()
280{
281 // this is here to avoid spurious opening after upload
282 if (millis() < 500)
283 return false;
284
285 bool result = false;
286
287 if (_usbLineInfo.lineState > 0)
288 {
289 result = true;
290 }
291
292 delay(10);
293 return result;
294}
295
296int32_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
316unsigned long Serial_::baud() {
317 return _usbLineInfo.dwDTERate;
318}
319
320uint8_t Serial_::stopbits() {
321 return _usbLineInfo.bCharFormat;
322}
323
324uint8_t Serial_::paritytype() {
325 return _usbLineInfo.bParityType;
326}
327
328uint8_t Serial_::numbits() {
329 return _usbLineInfo.bDataBits;
330}
331
332bool Serial_::dtr() {
333 return _usbLineInfo.lineState & 0x1;
334}
335
336bool Serial_::rts() {
337 return _usbLineInfo.lineState & 0x2;
338}
339
340Serial_ SerialUSB(USBDevice);
341
342#endif
Note: See TracBrowser for help on using the repository browser.