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

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

ライブラリとOS及びベーシックなサンプルの追加.

File size: 7.0 KB
Line 
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.
15*/
16
17#include <stdlib.h>
18#include <stdio.h>
19#include <stdint.h>
20
21// 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
32
33#ifdef CDC_ENABLED
34
35#define CDC_SERIAL_BUFFER_SIZE 64
36
37/* For information purpose only since RTS is not always handled by the terminal application */
38#define CDC_LINESTATE_DTR 0x01 // Data Terminal Ready
39#define CDC_LINESTATE_RTS 0x02 // Ready to Send
40
41#define CDC_LINESTATE_READY (CDC_LINESTATE_RTS | CDC_LINESTATE_DTR)
42
43struct ring_buffer
44{
45 uint8_t buffer[CDC_SERIAL_BUFFER_SIZE];
46 volatile uint32_t head;
47 volatile uint32_t tail;
48};
49
50ring_buffer cdc_rx_buffer = { { 0 }, 0, 0};
51
52typedef struct
53{
54 uint32_t dwDTERate;
55 uint8_t bCharFormat;
56 uint8_t bParityType;
57 uint8_t bDataBits;
58 uint8_t lineState;
59} LineInfo;
60
61_Pragma("pack(1)")
62static volatile LineInfo _usbLineInfo = {
63 115200, // dWDTERate
64 0x00, // bCharFormat
65 0x00, // bParityType
66 0x08, // bDataBits
67 0x00 // lineState
68};
69
70static const CDCDescriptor _cdcInterface =
71{
72#if (defined CDC_ENABLED) && defined(HID_ENABLED)
73 D_IAD(0, 2, CDC_COMMUNICATION_INTERFACE_CLASS, CDC_ABSTRACT_CONTROL_MODEL, 0),
74#endif
75 // CDC communication interface
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 supported
80 D_CDCCS(CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0
81 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 // CDC data interface
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)
88};
89_Pragma("pack()")
90
91const void* WEAK CDC_GetInterface(void)
92{
93 return &_cdcInterface;
94}
95
96uint32_t WEAK CDC_GetInterfaceLength(void)
97{
98 return sizeof( _cdcInterface );
99}
100
101bool WEAK CDC_Setup(Setup& setup)
102{
103 uint8_t r = setup.bRequest;
104 uint8_t requestType = setup.bmRequestType;
105
106 if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
107 {
108 if (CDC_GET_LINE_CODING == r)
109 {
110 USBD_SendControl(0,(void*)&_usbLineInfo,7);
111 return true;
112 }
113 }
114
115 if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
116 {
117 if (CDC_SET_LINE_CODING == r)
118 {
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;
125 }
126
127 if (CDC_SET_CONTROL_LINE_STATE == r)
128 {
129 _usbLineInfo.lineState = setup.wValueL;
130 // auto-reset into the bootloader is triggered when the port, already
131 // open at 1200 bps, is closed.
132 if (1200 == _usbLineInfo.dwDTERate)
133 {
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 else
138 cancelReset();
139 }
140 return false;
141 }
142 }
143 return false;
144}
145
146uint32_t _serialPeek = -1;
147void Serial_::begin(uint32_t baud_count)
148{
149}
150
151void Serial_::begin(uint32_t baud_count, uint8_t config)
152{
153}
154
155void Serial_::end(void)
156{
157}
158
159void Serial_::accept(void)
160{
161 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
182int Serial_::available(void)
183{
184 ring_buffer *buffer = &cdc_rx_buffer;
185 return (uint32_t)(CDC_SERIAL_BUFFER_SIZE + buffer->head - buffer->tail) % CDC_SERIAL_BUFFER_SIZE;
186}
187
188int Serial_::peek(void)
189{
190 ring_buffer *buffer = &cdc_rx_buffer;
191
192 if (buffer->head == buffer->tail)
193 {
194 return -1;
195 }
196 else
197 {
198 return buffer->buffer[buffer->tail];
199 }
200}
201
202int Serial_::read(void)
203{
204 ring_buffer *buffer = &cdc_rx_buffer;
205
206 // if the head isn't ahead of the tail, we don't have any characters
207 if (buffer->head == buffer->tail)
208 {
209 return -1;
210 }
211 else
212 {
213 unsigned char c = buffer->buffer[buffer->tail];
214 buffer->tail = (uint32_t)(buffer->tail + 1) % CDC_SERIAL_BUFFER_SIZE;
215 if (USBD_Available(CDC_ENDPOINT_OUT))
216 accept();
217 return c;
218 }
219}
220
221void Serial_::flush(void)
222{
223 USBD_Flush(CDC_ENDPOINT_IN);
224}
225
226size_t Serial_::write(const uint8_t *buffer, size_t size)
227{
228 /* only try to send bytes if the high-level CDC connection itself
229 is open (not just the pipe) - the OS should set lineState when the port
230 is opened and clear lineState when the port is closed.
231 bytes sent before the user opens the connection or after
232 the connection is closed are lost - just like with a UART. */
233
234 {
235 uint32_t r = USBD_Send(CDC_ENDPOINT_IN, buffer, size);
236
237 if (r > 0)
238 {
239 return r;
240 } else
241 {
242 setWriteError();
243 return 0;
244 }
245 }
246 setWriteError();
247 return 0;
248}
249
250size_t Serial_::write(uint8_t c) {
251 return write(&c, 1);
252}
253
254// This operator is a convenient way for a sketch to check whether the
255// port has actually been configured and opened by the host (as opposed
256// to just being connected to the host). It can be used, for example, in
257// setup() before printing to ensure that an application on the host is
258// actually ready to receive and display the data.
259// We add a short delay before returning to fix a bug observed by Federico
260// where the port is configured (lineState != 0) but not quite opened.
261
262Serial_::operator bool()
263{
264 // this is here to avoid spurious opening after upload
265 if (millis() < 500)
266 return false;
267
268 bool result = false;
269
270 if (_usbLineInfo.lineState > 0)
271 {
272 result = true;
273 }
274
275 delay(10);
276 return result;
277}
278
279Serial_ SerialUSB;
280
281#endif
Note: See TracBrowser for help on using the repository browser.