COSA
An Object-Oriented Platform for Arduino Programming
CDC.cpp
Go to the documentation of this file.
1 
22 #include "Cosa/CDC.hh"
23 
24 #if defined(USBCON)
25 
26 #include "Cosa/USB/Platform.h"
27 #include "Cosa/IOBuffer.hh"
28 #include "Cosa/Watchdog.hh"
29 #include "Cosa/Power.hh"
30 #include <avr/wdt.h>
31 
33 CDC __attribute__((weak)) cdc(&ibuf);
34 
35 typedef struct {
36  uint32_t dwDTERate;
37  uint8_t bCharFormat;
38  uint8_t bParityType;
39  uint8_t bDataBits;
40  uint8_t lineState;
41 } LineInfo;
42 
43 static volatile LineInfo _usbLineInfo = {
44  57600, 0x00, 0x00, 0x00, 0x00
45 };
46 
47 int CDC_GetInterface(uint8_t* interfaceNum) __attribute__ ((weak));
48 bool CDC_Setup(Setup& setup) __attribute__ ((weak));
49 
50 extern const CDCDescriptor _cdcInterface PROGMEM;
51 const CDCDescriptor _cdcInterface = {
53  // CDC communication interface
55  // Header (1.10 bcd)
56  D_CDCCS(CDC_HEADER,0x10,0x01),
57  // Device handles call management (not)
59  // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported
61  // Communication interface is master, data interface is slave 0
64  // CDC data interface
68 };
69 
70 int
71 CDC_GetInterface(uint8_t* interfaceNum)
72 {
73  interfaceNum[0] += 2;
74  return USB_SendControl(TRANSFER_PGM,&_cdcInterface,sizeof(_cdcInterface));
75 }
76 
77 bool
78 CDC_Setup(Setup& setup)
79 {
80  uint8_t r = setup.bRequest;
81  uint8_t requestType = setup.bmRequestType;
82 
83  if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) {
84  if (CDC_GET_LINE_CODING == r) {
85  USB_SendControl(0,(void*)&_usbLineInfo,7);
86  return (true);
87  }
88  }
89 
90  if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) {
91  if (CDC_SET_LINE_CODING == r) {
92  USB_RecvControl((void*)&_usbLineInfo,7);
93  return (true);
94  }
95 
96  if (CDC_SET_CONTROL_LINE_STATE == r) {
97  _usbLineInfo.lineState = setup.wValueL;
98 
99  // auto-reset into the bootloader is triggered when the port, already
100  // open at 1200 bps, is closed. this is the signal to start the watchdog
101  // with a relatively long period so it can finish housekeeping tasks
102  // like servicing endpoints before the sketch ends
103  if (1200 == _usbLineInfo.dwDTERate) {
104  // We check DTR state to determine if host port is open (bit 0
105  // of lineState).
106  if ((_usbLineInfo.lineState & 0x01) == 0) {
107  *(uint16_t*) 0x0800 = 0x7777;
108  wdt_enable(WDTO_120MS);
109  }
110  else {
111  // Most OSs do some intermediate steps when configuring
112  // ports and DTR can twiggle more than once before
113  // stabilizing. To avoid spurious resets we set the watchdog
114  // to 120ms and eventually cancel if DTR goes back high.
115  wdt_disable();
116  wdt_reset();
117  *(uint16_t *)0x0800 = 0x0;
118  }
119  }
120  return (true);
121  }
122 
123  if (CDC_SEND_BREAK == r) {
124  // lost serial connection; mark lineState as gone
125  _usbLineInfo.lineState = 0;
126  return (true);
127  }
128  }
129  return (false);
130 }
131 
132 bool
133 CDC::begin(uint32_t baudrate, uint8_t format)
134 {
135  UNUSED(baudrate);
136  UNUSED(format);
137  Power::usb_enable();
139  if (!USBDevice.attach()) return (false);
140  for (uint8_t retry = 0; retry < 30; retry++) {
141  if (_usbLineInfo.lineState > 0) return (true);
142  delay(200);
143  }
144  delay(1000);
145  return (false);
146 }
147 
148 void
149 CDC::accept()
150 {
151  while (m_ibuf->room()) {
152  int c = USB_Recv(CDC_RX);
153  if (c == IOStream::EOF) break;
154  m_ibuf->putchar(c);
155  }
156 }
157 
158 int
159 CDC::flush(void)
160 {
161  USB_Flush(CDC_TX);
162  return (0);
163 }
164 
165 void
166 CDC::empty(void)
167 {
168  m_ibuf->empty();
169 }
170 
171 int
172 CDC::write(const void* buf, size_t size)
173 {
174  if ((_usbLineInfo.lineState & 0x01) &&
175  (USB_Send(CDC_TX, buf, size) != (int) size))
176  return (IOStream::EOF);
177 
178  return (size);
179 }
180 
181 #endif
#define CDC_HEADER
Definition: Core.h:121
#define CDC_UNION
Definition: Core.h:123
#define CDC_SEND_BREAK
Definition: Core.h:65
#define CDC_ACM_INTERFACE
Definition: Desc.h:48
#define CDC_ENDPOINT_IN
Definition: Desc.h:53
#define CDC_RX
Definition: Desc.h:62
#define CDC_ENDPOINT_OUT
Definition: Desc.h:52
#define REQUEST_HOSTTODEVICE_CLASS_INTERFACE
Definition: Core.h:58
#define CDC_DATA_INTERFACE_CLASS
Definition: Core.h:126
#define CDC_ENDPOINT_ACM
Definition: Desc.h:51
#define D_CDCCS(_subtype, _d0, _d1)
Definition: Core.h:292
#define CDC_SET_LINE_CODING
Definition: Core.h:62
#define CDC_GET_LINE_CODING
Definition: Core.h:63
#define USB_ENDPOINT_IN(addr)
Definition: Core.h:106
void(* delay)(uint32_t ms)
#define CDC_TX
Definition: Desc.h:63
#define USB_ENDPOINT_TYPE_INTERRUPT
Definition: Core.h:112
static void begin(uint16_t ms=16)
Definition: Watchdog.cpp:49
#define D_ENDPOINT(_addr, _attr, _packetSize, _interval)
Definition: Core.h:283
#define REQUEST_DEVICETOHOST_CLASS_INTERFACE
Definition: Core.h:55
#define CDC_CALL_MANAGEMENT
Definition: Core.h:119
#define CDC_COMMUNICATION_INTERFACE_CLASS
Definition: Core.h:117
#define D_IAD(_firstInterface, _count, _class, _subClass, _protocol)
Definition: Core.h:286
IOStream & flush(IOStream &outs)
Definition: IOStream.hh:853
#define UNUSED(x)
Definition: ATmega328P.hh:31
static const int EOF
Definition: IOStream.hh:33
#define USB_ENDPOINT_OUT(addr)
Definition: Core.h:105
#define CDC_SET_CONTROL_LINE_STATE
Definition: Core.h:64
#define CDC_DATA_INTERFACE
Definition: Desc.h:49
#define CDC_ABSTRACT_CONTROL_MODEL
Definition: Core.h:120
static bool is_initiated()
Definition: Watchdog.hh:41
static IOBuffer< UART::RX_BUFFER_MAX > ibuf
Definition: UART.cpp:37
#define USB_ENDPOINT_TYPE_BULK
Definition: Core.h:111
#define CDC_ABSTRACT_CONTROL_MANAGEMENT
Definition: Core.h:122
#define D_CDCCS4(_subtype, _d0)
Definition: Core.h:293
#define D_INTERFACE(_n, _numEndpoints, _class, _subClass, _protocol)
Definition: Core.h:280