18
18
19
19
#include < Arduino.h>
20
20
#include < Reset.h> // Needed for auto-reset with 1200bps port touch
21
+ #include " CDC.h"
22
+ #include " SAMD21_USBDevice.h"
21
23
22
24
#include < stdlib.h>
23
25
#include < stdio.h>
24
26
#include < stdint.h>
25
27
26
28
#ifdef CDC_ENABLED
27
29
30
+ extern USBDevice_SAMD21G18x usbd;
31
+
28
32
#define CDC_SERIAL_BUFFER_SIZE 256
29
33
30
34
/* For information purpose only since RTS is not always handled by the terminal application */
@@ -51,46 +55,94 @@ static volatile LineInfo _usbLineInfo = {
51
55
};
52
56
53
57
static volatile int32_t breakValue = -1 ;
58
+ _Pragma (" pack()" )
54
59
55
- static CDCDescriptor _cdcInterface = {
56
- D_IAD (0 , 2 , CDC_COMMUNICATION_INTERFACE_CLASS, CDC_ABSTRACT_CONTROL_MODEL, 0 ),
60
+ // CDC
61
+ #define CDC_ACM_INTERFACE pluggedInterface // CDC ACM
62
+ #define CDC_DATA_INTERFACE pluggedInterface+1 // CDC Data
63
+ #define CDC_ENDPOINT_ACM pluggedEndpoint
64
+ #define CDC_ENDPOINT_OUT pluggedEndpoint+1
65
+ #define CDC_ENDPOINT_IN pluggedEndpoint+2
57
66
58
- // CDC communication interface
59
- D_INTERFACE (CDC_ACM_INTERFACE, 1 , CDC_COMMUNICATION_INTERFACE_CLASS, CDC_ABSTRACT_CONTROL_MODEL, 0 ),
60
- D_CDCCS (CDC_HEADER, CDC_V1_10 & 0xFF , (CDC_V1_10>>8 ) & 0x0FF ), // Header (1.10 bcd)
67
+ #define CDC_RX CDC_ENDPOINT_OUT
68
+ #define CDC_TX CDC_ENDPOINT_IN
69
+
70
+ int Serial_::getInterface (uint8_t * interfaceNum)
71
+ {
72
+ interfaceNum[0 ] += 2 ; // uses 2
73
+ CDCDescriptor _cdcInterface = {
74
+ D_IAD (pluggedInterface, 2 , CDC_COMMUNICATION_INTERFACE_CLASS, CDC_ABSTRACT_CONTROL_MODEL, 0 ),
61
75
62
- D_CDCCS4 (CDC_ABSTRACT_CONTROL_MANAGEMENT, 6 ), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported
63
- D_CDCCS (CDC_UNION, CDC_ACM_INTERFACE, CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0
64
- D_CDCCS (CDC_CALL_MANAGEMENT, 1 , 1 ), // Device handles call management (not)
65
- D_ENDPOINT (USB_ENDPOINT_IN (CDC_ENDPOINT_ACM), USB_ENDPOINT_TYPE_INTERRUPT, 0x10 , 0x10 ),
76
+ // CDC communication interface
77
+ D_INTERFACE (CDC_ACM_INTERFACE, 1 , CDC_COMMUNICATION_INTERFACE_CLASS, CDC_ABSTRACT_CONTROL_MODEL, 0 ),
78
+ D_CDCCS (CDC_HEADER, CDC_V1_10 & 0xFF , (CDC_V1_10>>8 ) & 0x0FF ), // Header (1.10 bcd)
66
79
67
- // CDC data interface
68
- D_INTERFACE (CDC_DATA_INTERFACE, 2 , CDC_DATA_INTERFACE_CLASS, 0 , 0 ),
69
- D_ENDPOINT (USB_ENDPOINT_OUT (CDC_ENDPOINT_OUT), USB_ENDPOINT_TYPE_BULK, EPX_SIZE, 0 ),
70
- D_ENDPOINT (USB_ENDPOINT_IN (CDC_ENDPOINT_IN ), USB_ENDPOINT_TYPE_BULK, EPX_SIZE, 0 )
71
- };
72
- _Pragma (" pack()" )
80
+ D_CDCCS4 (CDC_ABSTRACT_CONTROL_MANAGEMENT, 6 ), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported
81
+ D_CDCCS (CDC_UNION, CDC_ACM_INTERFACE, CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0
82
+ D_CDCCS (CDC_CALL_MANAGEMENT, 1 , 1 ), // Device handles call management (not)
83
+ D_ENDPOINT (USB_ENDPOINT_IN (CDC_ENDPOINT_ACM), USB_ENDPOINT_TYPE_INTERRUPT, 0x10 , 0x10 ),
73
84
74
- const void * _CDC_GetInterface (void )
75
- {
76
- return &_cdcInterface;
85
+ // CDC data interface
86
+ D_INTERFACE (CDC_DATA_INTERFACE, 2 , CDC_DATA_INTERFACE_CLASS, 0 , 0 ),
87
+ D_ENDPOINT (USB_ENDPOINT_OUT (CDC_ENDPOINT_OUT), USB_ENDPOINT_TYPE_BULK, EPX_SIZE, 0 ),
88
+ D_ENDPOINT (USB_ENDPOINT_IN (CDC_ENDPOINT_IN), USB_ENDPOINT_TYPE_BULK, EPX_SIZE, 0 )
89
+ };
90
+
91
+ return USBDevice.sendControl (&_cdcInterface, sizeof (_cdcInterface));
77
92
}
78
93
79
- uint32_t _CDC_GetInterfaceLength ( void )
94
+ int Serial_::getDescriptor (USBSetup& setup )
80
95
{
81
- return sizeof (_cdcInterface) ;
96
+ return 0 ;
82
97
}
83
98
84
- int CDC_GetInterface (uint8_t * interfaceNum)
85
- {
86
- interfaceNum[0 ] += 2 ; // uses 2
87
- return USBDevice.sendControl (&_cdcInterface,sizeof (_cdcInterface));
99
+ static void utox8 (uint32_t val, char * s) {
100
+ for (int i = 0 ; i < 8 ; i++) {
101
+ int d = val & 0XF ;
102
+ val = (val >> 4 );
103
+
104
+ s[7 - i] = d > 9 ? ' A' + d - 10 : ' 0' + d;
105
+ }
106
+ }
107
+
108
+ uint8_t Serial_::getShortName (char * name) {
109
+ // from section 9.3.3 of the datasheet
110
+ #define SERIAL_NUMBER_WORD_0 *(volatile uint32_t *)(0x0080A00C )
111
+ #define SERIAL_NUMBER_WORD_1 *(volatile uint32_t *)(0x0080A040 )
112
+ #define SERIAL_NUMBER_WORD_2 *(volatile uint32_t *)(0x0080A044 )
113
+ #define SERIAL_NUMBER_WORD_3 *(volatile uint32_t *)(0x0080A048 )
114
+
115
+ utox8 (SERIAL_NUMBER_WORD_0, &name[0 ]);
116
+ utox8 (SERIAL_NUMBER_WORD_1, &name[8 ]);
117
+ utox8 (SERIAL_NUMBER_WORD_2, &name[16 ]);
118
+ utox8 (SERIAL_NUMBER_WORD_3, &name[24 ]);
119
+ return 32 ;
88
120
}
89
121
90
- bool CDC_Setup (USBSetup& setup)
122
+ void Serial_::handleEndpoint (int ep) {
123
+ if (ep == CDC_ENDPOINT_IN)
124
+ {
125
+ // NAK on endpoint IN, the bank is not yet filled in.
126
+ usbd.epBank1ResetReady (CDC_ENDPOINT_IN);
127
+ usbd.epBank1AckTransferComplete (CDC_ENDPOINT_IN);
128
+ }
129
+ if (ep == CDC_ENDPOINT_ACM)
130
+ {
131
+ // NAK on endpoint IN, the bank is not yet filled in.
132
+ usbd.epBank1ResetReady (CDC_ENDPOINT_ACM);
133
+ usbd.epBank1AckTransferComplete (CDC_ENDPOINT_ACM);
134
+ }
135
+ }
136
+
137
+ bool Serial_::setup (USBSetup& setup)
91
138
{
92
139
uint8_t requestType = setup.bmRequestType ;
93
140
uint8_t r = setup.bRequest ;
141
+ uint8_t i = setup.wIndex ;
142
+
143
+ if (CDC_ACM_INTERFACE != i) {
144
+ return false ;
145
+ }
94
146
95
147
if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE)
96
148
{
@@ -103,6 +155,7 @@ bool CDC_Setup(USBSetup& setup)
103
155
104
156
if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE)
105
157
{
158
+
106
159
if (r == CDC_SET_LINE_CODING)
107
160
{
108
161
USBDevice.recvControl ((void *)&_usbLineInfo, 7 );
@@ -126,18 +179,32 @@ bool CDC_Setup(USBSetup& setup)
126
179
{
127
180
cancelReset ();
128
181
}
129
- return false ;
182
+ USBDevice. sendZlp ( 0 ) ;
130
183
}
131
184
132
185
if (CDC_SEND_BREAK == r)
133
186
{
134
187
breakValue = ((uint16_t )setup.wValueH << 8 ) | setup.wValueL ;
135
- return false ;
188
+ USBDevice. sendZlp ( 0 ) ;
136
189
}
190
+ return true ;
137
191
}
138
192
return false ;
139
193
}
140
194
195
+ Serial_::Serial_ (USBDeviceClass &_usb) : PluggableUSBModule(3 , 2 , epType), usb(_usb), stalled(false )
196
+ {
197
+ epType[0 ] = USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN (0 );
198
+ epType[1 ] = USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_OUT (0 );
199
+ epType[2 ] = USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN (0 );
200
+ PluggableUSB ().plug (this );
201
+ }
202
+
203
+ void Serial_::enableInterrupt () {
204
+ usbd.epBank1EnableTransferComplete (CDC_ENDPOINT_ACM);
205
+ usbd.epBank0EnableTransferComplete (CDC_ENDPOINT_OUT);
206
+ }
207
+
141
208
void Serial_::begin (uint32_t /* baud_count */ )
142
209
{
143
210
// uart config is ignored in USB-CDC
0 commit comments