18
18
19
19
#include " USBAPI.h"
20
20
#include < avr/wdt.h>
21
+ #include < util/atomic.h>
21
22
22
23
#if defined(USBCON)
23
- #ifdef CDC_ENABLED
24
24
25
25
typedef struct
26
26
{
@@ -32,6 +32,7 @@ typedef struct
32
32
} LineInfo;
33
33
34
34
static volatile LineInfo _usbLineInfo = { 57600 , 0x00 , 0x00 , 0x00 , 0x00 };
35
+ static volatile int32_t breakValue = -1 ;
35
36
36
37
#define WEAK __attribute__ ((weak))
37
38
@@ -50,17 +51,17 @@ const CDCDescriptor _cdcInterface =
50
51
51
52
// CDC data interface
52
53
D_INTERFACE (CDC_DATA_INTERFACE,2 ,CDC_DATA_INTERFACE_CLASS,0 ,0 ),
53
- D_ENDPOINT (USB_ENDPOINT_OUT (CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,0x40 ,0 ),
54
- D_ENDPOINT (USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,0x40 ,0 )
54
+ D_ENDPOINT (USB_ENDPOINT_OUT (CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,USB_EP_SIZE ,0 ),
55
+ D_ENDPOINT (USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,USB_EP_SIZE ,0 )
55
56
};
56
57
57
- int WEAK CDC_GetInterface (u8 * interfaceNum)
58
+ int CDC_GetInterface (u8 * interfaceNum)
58
59
{
59
60
interfaceNum[0 ] += 2 ; // uses 2
60
61
return USB_SendControl (TRANSFER_PGM,&_cdcInterface,sizeof (_cdcInterface));
61
62
}
62
63
63
- bool WEAK CDC_Setup (Setup & setup)
64
+ bool CDC_Setup (USBSetup & setup)
64
65
{
65
66
u8 r = setup.bRequest ;
66
67
u8 requestType = setup.bmRequestType ;
@@ -76,6 +77,11 @@ bool WEAK CDC_Setup(Setup& setup)
76
77
77
78
if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
78
79
{
80
+ if (CDC_SEND_BREAK == r)
81
+ {
82
+ breakValue = ((uint16_t )setup.wValueH << 8 ) | setup.wValueL ;
83
+ }
84
+
79
85
if (CDC_SET_LINE_CODING == r)
80
86
{
81
87
USB_RecvControl ((void *)&_usbLineInfo,7 );
@@ -93,10 +99,24 @@ bool WEAK CDC_Setup(Setup& setup)
93
99
// with a relatively long period so it can finish housekeeping tasks
94
100
// like servicing endpoints before the sketch ends
95
101
102
+ #ifndef MAGIC_KEY
103
+ #define MAGIC_KEY 0x7777
104
+ #endif
105
+ #ifndef MAGIC_KEY_POS
106
+ #define MAGIC_KEY_POS 0x0800
107
+ #endif
108
+
96
109
// We check DTR state to determine if host port is open (bit 0 of lineState).
97
110
if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01 ) == 0 )
98
111
{
99
- *(uint16_t *)0x0800 = 0x7777 ;
112
+ #if MAGIC_KEY_POS != (RAMEND-1)
113
+ *(uint16_t *)(RAMEND-1 ) = *(uint16_t *)MAGIC_KEY_POS;
114
+ *(uint16_t *)MAGIC_KEY_POS = MAGIC_KEY;
115
+ #else
116
+ // for future boards save the key in the inproblematic RAMEND
117
+ // which is reserved for the main() return value (which will never return)
118
+ *(uint16_t *)MAGIC_KEY_POS = MAGIC_KEY;
119
+ #endif
100
120
wdt_enable (WDTO_120MS);
101
121
}
102
122
else
@@ -108,7 +128,11 @@ bool WEAK CDC_Setup(Setup& setup)
108
128
109
129
wdt_disable ();
110
130
wdt_reset ();
111
- *(uint16_t *)0x0800 = 0x0 ;
131
+ #if MAGIC_KEY_POS != (RAMEND-1)
132
+ *(uint16_t *)MAGIC_KEY_POS = *(uint16_t *)(RAMEND-1 );
133
+ #else
134
+ *(uint16_t *)MAGIC_KEY_POS = 0x0000 ;
135
+ #endif
112
136
}
113
137
}
114
138
return true ;
@@ -156,6 +180,11 @@ int Serial_::read(void)
156
180
return USB_Recv (CDC_RX);
157
181
}
158
182
183
+ int Serial_::availableForWrite (void )
184
+ {
185
+ return USB_SendSpace (CDC_TX);
186
+ }
187
+
159
188
void Serial_::flush (void )
160
189
{
161
190
USB_Flush (CDC_TX);
@@ -205,7 +234,46 @@ Serial_::operator bool() {
205
234
return result;
206
235
}
207
236
237
+ unsigned long Serial_::baud () {
238
+ // Disable interrupts while reading a multi-byte value
239
+ uint32_t baudrate;
240
+ ATOMIC_BLOCK (ATOMIC_RESTORESTATE) {
241
+ baudrate = _usbLineInfo.dwDTERate ;
242
+ }
243
+ return baudrate;
244
+ }
245
+
246
+ uint8_t Serial_::stopbits () {
247
+ return _usbLineInfo.bCharFormat ;
248
+ }
249
+
250
+ uint8_t Serial_::paritytype () {
251
+ return _usbLineInfo.bParityType ;
252
+ }
253
+
254
+ uint8_t Serial_::numbits () {
255
+ return _usbLineInfo.bDataBits ;
256
+ }
257
+
258
+ bool Serial_::dtr () {
259
+ return _usbLineInfo.lineState & 0x1 ;
260
+ }
261
+
262
+ bool Serial_::rts () {
263
+ return _usbLineInfo.lineState & 0x2 ;
264
+ }
265
+
266
+ int32_t Serial_::readBreak () {
267
+ int32_t ret;
268
+ // Disable IRQs while reading and clearing breakValue to make
269
+ // sure we don't overwrite a value just set by the ISR.
270
+ ATOMIC_BLOCK (ATOMIC_RESTORESTATE) {
271
+ ret = breakValue;
272
+ breakValue = -1 ;
273
+ }
274
+ return ret;
275
+ }
276
+
208
277
Serial_ Serial;
209
278
210
- #endif
211
279
#endif /* if defined(USBCON) */
0 commit comments