25
25
26
26
typedef struct
27
27
{
28
- u32 dwDTERate;
29
- u8 bCharFormat;
30
- u8 bParityType;
31
- u8 bDataBits;
32
- u8 lineState;
28
+ u32 dwDTERate;
29
+ u8 bCharFormat;
30
+ u8 bParityType;
31
+ u8 bDataBits;
32
+ u8 lineState;
33
33
} LineInfo;
34
34
35
35
static volatile LineInfo _usbLineInfo = { 57600 , 0x00 , 0x00 , 0x00 , 0x00 };
@@ -39,89 +39,107 @@ static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 };
39
39
extern const CDCDescriptor _cdcInterface PROGMEM;
40
40
const CDCDescriptor _cdcInterface =
41
41
{
42
- D_IAD (0 ,2 ,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1 ),
43
-
44
- // CDC communication interface
45
- D_INTERFACE (CDC_ACM_INTERFACE,1 ,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0 ),
46
- D_CDCCS (CDC_HEADER,0x10 ,0x01 ), // Header (1.10 bcd)
47
- D_CDCCS (CDC_CALL_MANAGEMENT,1 ,1 ), // Device handles call management (not)
48
- D_CDCCS4 (CDC_ABSTRACT_CONTROL_MANAGEMENT,6 ), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported
49
- D_CDCCS (CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0
50
- D_ENDPOINT (USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10 ,0x40 ),
51
-
52
- // CDC data interface
53
- D_INTERFACE (CDC_DATA_INTERFACE,2 ,CDC_DATA_INTERFACE_CLASS,0 ,0 ),
54
- D_ENDPOINT (USB_ENDPOINT_OUT (CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,0x40 ,0 ),
55
- D_ENDPOINT (USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,0x40 ,0 )
42
+ D_IAD (0 ,2 ,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1 ),
43
+
44
+ // CDC communication interface
45
+ D_INTERFACE (CDC_ACM_INTERFACE,1 ,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0 ),
46
+ D_CDCCS (CDC_HEADER,0x10 ,0x01 ), // Header (1.10 bcd)
47
+ D_CDCCS (CDC_CALL_MANAGEMENT,1 ,1 ), // Device handles call management (not)
48
+ D_CDCCS4 (CDC_ABSTRACT_CONTROL_MANAGEMENT,6 ), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported
49
+ D_CDCCS (CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0
50
+ D_ENDPOINT (USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10 ,0x40 ),
51
+
52
+ // CDC data interface
53
+ D_INTERFACE (CDC_DATA_INTERFACE,2 ,CDC_DATA_INTERFACE_CLASS,0 ,0 ),
54
+ D_ENDPOINT (USB_ENDPOINT_OUT (CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,0x40 ,0 ),
55
+ D_ENDPOINT (USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,0x40 ,0 )
56
56
};
57
57
58
58
int WEAK CDC_GetInterface (u8* interfaceNum)
59
59
{
60
- interfaceNum[0 ] += 2 ; // uses 2
61
- return USB_SendControl (TRANSFER_PGM,&_cdcInterface,sizeof (_cdcInterface));
60
+ interfaceNum[0 ] += 2 ; // uses 2
61
+ return USB_SendControl (TRANSFER_PGM,&_cdcInterface,sizeof (_cdcInterface));
62
62
}
63
63
64
64
bool WEAK CDC_Setup (Setup& setup)
65
65
{
66
- u8 r = setup.bRequest ;
67
- u8 requestType = setup.bmRequestType ;
68
-
69
- if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
70
- {
71
- if (CDC_GET_LINE_CODING == r)
72
- {
73
- USB_SendControl (0 ,(void *)&_usbLineInfo,7 );
74
- return true ;
75
- }
76
- }
77
-
78
- if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
79
- {
80
- if (CDC_SET_LINE_CODING == r)
81
- {
82
- USB_RecvControl ((void *)&_usbLineInfo,7 );
83
- return true ;
84
- }
85
-
86
- if (CDC_SET_CONTROL_LINE_STATE == r)
87
- {
88
- _usbLineInfo.lineState = setup.wValueL ;
89
-
90
- // auto-reset into the bootloader is triggered when the port, already
91
- // open at 1200 bps, is closed. this is the signal to start the watchdog
92
- // with a relatively long period so it can finish housekeeping tasks
93
- // like servicing endpoints before the sketch ends
94
- if (1200 == _usbLineInfo.dwDTERate ) {
95
- // We check DTR state to determine if host port is open (bit 0 of lineState).
96
- if ((_usbLineInfo.lineState & 0x01 ) == 0 ) {
97
- *(uint16_t *)0x0800 = 0x7777 ;
98
- wdt_enable (WDTO_120MS);
99
- } else {
100
- // Most OSs do some intermediate steps when configuring ports and DTR can
101
- // twiggle more than once before stabilizing.
102
- // To avoid spurious resets we set the watchdog to 250ms and eventually
103
- // cancel if DTR goes back high.
104
-
105
- wdt_disable ();
106
- wdt_reset ();
107
- *(uint16_t *)0x0800 = 0x0 ;
108
- }
109
- }
110
- return true ;
111
- }
112
- }
113
- return false ;
66
+ u8 r = setup.bRequest ;
67
+ u8 requestType = setup.bmRequestType ;
68
+
69
+ if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
70
+ {
71
+ if (CDC_GET_LINE_CODING == r)
72
+ {
73
+ #if 1
74
+ USB_SendControl (0 ,(void *)&_usbLineInfo,7 );
75
+ #endif // 0
76
+ return true ;
77
+ }
78
+ }
79
+
80
+ if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
81
+ {
82
+ if (CDC_SET_LINE_CODING == r)
83
+ {
84
+ #if 1
85
+ USB_RecvControl ((void *)&_usbLineInfo,7 );
86
+ #endif // 0
87
+ return true ;
88
+ }
89
+ // NOTE: this next part is for the 'caterina' CDC bootloader, arduino/bootloaders/caterina/Caterina.c
90
+ // it has some "special" code in it, like using 0x0800 in RAM as an address for a 'key' (7777H)
91
+ // to indicate it was soft-booted. XMEGA has better ways of handling this, like a CPU flag that
92
+ // indicates "I was soft-booted" as one example, and a 'WDT' timeout flag on top of that.
93
+ if (CDC_SET_CONTROL_LINE_STATE == r)
94
+ {
95
+ _usbLineInfo.lineState = setup.wValueL ;
96
+
97
+ // auto-reset into the bootloader is triggered when the port, already
98
+ // open at 1200 bps, is closed. this is the signal to start the watchdog
99
+ // with a relatively long period so it can finish housekeeping tasks
100
+ // like servicing endpoints before the sketch ends
101
+ if (1200 == _usbLineInfo.dwDTERate )
102
+ {
103
+ // We check DTR state to determine if host port is open (bit 0 of lineState).
104
+ if ((_usbLineInfo.lineState & 0x01 ) == 0 )
105
+ {
106
+ // This section of code is support for the 'caterina' bootloader, which allows USB flashing (apparently)
107
+ //
108
+ // *(uint16_t *)0x0800 = 0x7777; note that on XMEGA this is a VERY bad thing
109
+ // wdt_enable(WDTO_120MS);
110
+
111
+ // TODO: timeout-based reboot
112
+ }
113
+ else // 3 lines better than 1 - ALLMAN STYLE! - do *NOT* do '} else {' - BLEAH!
114
+ {
115
+ // Most OSs do some intermediate steps when configuring ports and DTR can
116
+ // twiggle more than once before stabilizing.
117
+ // To avoid spurious resets we set the watchdog to 250ms and eventually
118
+ // cancel if DTR goes back high.
119
+
120
+ // This section of code is support for the 'caterina' bootloader, which allows USB flashing (apparently)
121
+ //
122
+ // TODO: reset whatever boot timeout I did
123
+ // wdt_disable();
124
+ // wdt_reset();
125
+ // *(uint16_t *)0x0800 = 0x0; note that on XMEGA this is a VERY bad thing
126
+ }
127
+ }
128
+ return true ;
129
+ }
130
+ }
131
+ return false ;
114
132
}
115
133
116
134
117
135
void Serial_::begin (unsigned long baud_count)
118
136
{
119
- peek_buffer = -1 ;
137
+ peek_buffer = -1 ;
120
138
}
121
139
122
140
void Serial_::begin (unsigned long baud_count, byte config)
123
141
{
124
- peek_buffer = -1 ;
142
+ peek_buffer = -1 ;
125
143
}
126
144
127
145
void Serial_::end (void )
@@ -130,61 +148,69 @@ void Serial_::end(void)
130
148
131
149
int Serial_::available (void )
132
150
{
133
- if (peek_buffer >= 0 ) {
134
- return 1 + USB_Available (CDC_RX);
135
- }
136
- return USB_Available (CDC_RX);
151
+ if (peek_buffer >= 0 )
152
+ {
153
+ return 1 + USB_Available (CDC_RX);
154
+ }
155
+ return USB_Available (CDC_RX);
137
156
}
138
157
139
158
int Serial_::peek (void )
140
159
{
141
- if (peek_buffer < 0 )
142
- peek_buffer = USB_Recv (CDC_RX);
143
- return peek_buffer;
160
+ if (peek_buffer < 0 )
161
+ {
162
+ peek_buffer = USB_Recv (CDC_RX);
163
+ }
164
+ return peek_buffer;
144
165
}
145
166
146
167
int Serial_::read (void )
147
168
{
148
- if (peek_buffer >= 0 ) {
149
- int c = peek_buffer;
150
- peek_buffer = -1 ;
151
- return c;
152
- }
153
- return USB_Recv (CDC_RX);
169
+ if (peek_buffer >= 0 )
170
+ {
171
+ int c = peek_buffer;
172
+ peek_buffer = -1 ;
173
+ return c;
174
+ }
175
+ return USB_Recv (CDC_RX);
154
176
}
155
177
156
178
void Serial_::flush (void )
157
179
{
158
- USB_Flush (CDC_TX);
180
+ USB_Flush (CDC_TX);
159
181
}
160
182
161
183
size_t Serial_::write (uint8_t c)
162
184
{
163
- return write (&c, 1 );
185
+ return write (&c, 1 );
164
186
}
165
187
166
188
size_t Serial_::write (const uint8_t *buffer, size_t size)
167
189
{
168
- /* only try to send bytes if the high-level CDC connection itself
169
- is open (not just the pipe) - the OS should set lineState when the port
170
- is opened and clear lineState when the port is closed.
171
- bytes sent before the user opens the connection or after
172
- the connection is closed are lost - just like with a UART. */
173
-
174
- // TODO - ZE - check behavior on different OSes and test what happens if an
175
- // open connection isn't broken cleanly (cable is yanked out, host dies
176
- // or locks up, or host virtual serial port hangs)
177
- if (_usbLineInfo.lineState > 0 ) {
178
- int r = USB_Send (CDC_TX,buffer,size);
179
- if (r > 0 ) {
180
- return r;
181
- } else {
182
- setWriteError ();
183
- return 0 ;
184
- }
185
- }
186
- setWriteError ();
187
- return 0 ;
190
+ /* only try to send bytes if the high-level CDC connection itself
191
+ is open (not just the pipe) - the OS should set lineState when the port
192
+ is opened and clear lineState when the port is closed.
193
+ bytes sent before the user opens the connection or after
194
+ the connection is closed are lost - just like with a UART. */
195
+
196
+ // TODO - ZE - check behavior on different OSes and test what happens if an
197
+ // open connection isn't broken cleanly (cable is yanked out, host dies
198
+ // or locks up, or host virtual serial port hangs)
199
+ if (_usbLineInfo.lineState > 0 )
200
+ {
201
+ int r = USB_Send (CDC_TX,buffer,size);
202
+ if (r > 0 )
203
+ {
204
+ return r;
205
+ }
206
+ else
207
+ {
208
+ setWriteError ();
209
+ return 0 ;
210
+ }
211
+ }
212
+ setWriteError ();
213
+ return 0 ;
188
214
}
189
215
190
216
// This operator is a convenient way for a sketch to check whether the
@@ -194,15 +220,19 @@ size_t Serial_::write(const uint8_t *buffer, size_t size)
194
220
// actually ready to receive and display the data.
195
221
// We add a short delay before returning to fix a bug observed by Federico
196
222
// where the port is configured (lineState != 0) but not quite opened.
197
- Serial_::operator bool () {
198
- bool result = false ;
199
- if (_usbLineInfo.lineState > 0 )
200
- result = true ;
201
- delay (10 );
202
- return result;
223
+ Serial_::operator bool ()
224
+ {
225
+ bool result = false ;
226
+ if (_usbLineInfo.lineState > 0 )
227
+ {
228
+ result = true ;
229
+ }
230
+ delay (10 );
231
+ return result;
203
232
}
204
233
205
234
Serial_ Serial;
206
235
207
236
#endif
208
237
#endif /* if defined(USBCON) */
238
+
0 commit comments