Jussipo has made USB split mode enabled
and dual VCP work on his side. So I started looking into this issue, fixed two
defects and make three VCPs work. Here is the summary.
1. Enable USB split mode
In src\LUFA\Drivers\USB\Core\SIM3u\Endpoint_SIM3U.c
... ... @@
-54,15 +54,15 @@ bool Endpoint_ConfigureEndpoint(const uint8_t Address,
54 54
55 55
if(Number !=
ENDPOINT_CONTROLEP)
56 56
{
57 - ep_config
= 0x450024; // bit 2,5,16,18,22 must be writen
58 -
57 + ep_config
= 0x450424; // bit 2,5,10,16,18,22 must
be written
58 + //IURF,ISTSTLI,SPLITEN,
OPRDYI,OORF,OSTSTLI
59 59
if(Type
== EP_TYPE_ISOCHRONOUS)
60 60
{ // ISO transfer need set "1"
61 61
ep_config
|= (SI32_USBEP_A_EPCONTROL_IISOEN_ISO_U32);
62 62
}
63 63
if(dir_sel)
64 64
{ // IN endpoint
65 - ep_config
|= (SI32_USBEP_A_EPCONTROL_DIRSEL_IN_U32|SI32_USBEP_A_EPCONTROL_ICLRDT_RESET_U32);
65 + ep_config |=
(SI32_USBEP_A_EPCONTROL_ICLRDT_RESET_U32);
66 66
SI32_USBEP_A_set_in_max_packet_size(USB_EPn(Number),Size>>3);
67 67
}
68 68
else
2. Make a function to
sent endpoint direction.
In
src\LUFA\Drivers\USB\Core\SIM3u\Endpoint_SIM3U.h
... ... @@
-591,7 +591,11 @@
591 591
static
inline void Endpoint_SetEndpointDirection(const uint32_t DirectionMask)
ATTR_ALWAYS_INLINE;
592 592
static
inline void Endpoint_SetEndpointDirection(const uint32_t DirectionMask)
593 593
{
594 - return;
594 + if( DirectionMask ==
ENDPOINT_DIR_IN)
595 +
USB_EPn(usb_ep_selected)->EPCONTROL.DIRSEL = 1;
596 + else
597 +
USB_EPn(usb_ep_selected)->EPCONTROL.DIRSEL = 0;
598 + return;
595 599
}
3. Add Endpoint_SetEndpointDirection() call in CDC
send/receive function
In src\LUFA\Drivers\USB\Class\Devcie\CDCClassDevice.c
old new
... ... @@
-160,6 +160,7 @@ uint8_t CDC_Device_SendData(USB_ClassInfo_CDC_Device_t* const
CDCInterfaceInfo,
160 160
if ((USB_DeviceState !=
DEVICE_STATE_Configured) ||
!(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
161 161
return ENDPOINT_RWSTREAM_DeviceDisconnected;
162 162
163 + Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
163 164
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address);
164 165
return
Endpoint_Write_Stream_LE(Buffer, Length, NULL);
165 166
}
... ... @@
-249,6 +250,7 @@ int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t*
const CDCInterfaceInf
249 250
250 251
int16_t ReceivedByte = -1;
251 252
253 + Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT);
252 254
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpoint.Address);
253 255
254 256
if (Endpoint_IsOUTReceived())
4. Prepared three individual INF files for one, two,
three VCPs
Main modifications are list below.
In src\VirtualSerial\
88 +[DeviceList]
89 +%DESCRIPTION%=
DriverInstall,USB\VID_10C4&PID_A012&MI_00,
USB\VID_10C4&PID_A012&MI_02
90 +
91 +[DeviceList.NTamd64]
92 +%DESCRIPTION%=
DriverInstall,USB\VID_10C4&PID_A012&MI_00,
USB\VID_10C4&PID_A012&MI_02
5. Three VCP share same interrupt endpoint, and each BULK
in/out endpoint number is same since we use USB split mode.
In src\VirtualSerial\Descriptors.h
... ... @@
-40,15 +40,33 @@
40 40
#include
41 41
42 42
/* Macros: */
43 + #define DUAL_VCP_ENABLE 1
44 + #define TRI_VCP_ENABLE 0
45 +
43 46
/**
Endpoint address of the CDC device-to-host notification IN endpoint. */
44 47
#define
CDC_NOTIFICATION_EPADDR
(ENDPOINT_DIR_IN | 1)
45 48
46 - /**
Endpoint address of the CDC device-to-host data IN endpoint. */
47 - #define
CDC_TX_EPADDR
(ENDPOINT_DIR_IN | 2)
49 + /** Endpoint address of the CDC1
device-to-host data IN endpoint. */
50 + #define
CDC1_TX_EPADDR
(ENDPOINT_DIR_IN | 2)
51 +
52 + /**
Endpoint address of the CDC1 host-to-device data OUT endpoint. */
53 + #define
CDC1_RX_EPADDR
(ENDPOINT_DIR_OUT | 2)
54 +
55 +#if
(DUAL_VCP_ENABLE || TRI_VCP_ENABLE)
56 + /** Endpoint address of the CDC2
device-to-host data IN endpoint. */
57 + #define CDC2_TX_EPADDR (ENDPOINT_DIR_IN | 3)
58 +
59 + /** Endpoint address of the CDC2
host-to-device data OUT endpoint. */
60 + #define CDC2_RX_EPADDR (ENDPOINT_DIR_OUT | 3)
61 +#endif
48 62
49 - /**
Endpoint address of the CDC host-to-device data OUT endpoint. */
50 - #define
CDC_RX_EPADDR
(ENDPOINT_DIR_OUT | 3)
63 +#if
(TRI_VCP_ENABLE)
64 + /** Endpoint address of the CDC3
device-to-host data IN endpoint. */
65 + #define CDC3_TX_EPADDR (ENDPOINT_DIR_IN | 4)
51 66
67 + /** Endpoint address of the CDC3
host-to-device data OUT endpoint. */
68 + #define CDC3_RX_EPADDR (ENDPOINT_DIR_OUT | 4)
69 +#endif
6. Add IAD, second and third VCP descriptions.
In src\VirtualSerial\Descriptors.c
Here are part of modifications.
old new
... ... @@
-47,15 +47,21 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
47 47
{
48 48
.Header = {.Size =
sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
49 49
50 - .USBSpecification = VERSION_BCD(01.10),
51 - .Class = CDC_CSCP_CDCClass,
52 - .SubClass = CDC_CSCP_NoSpecificSubclass,
53 - .Protocol = CDC_CSCP_NoSpecificProtocol,
50 + .USBSpecification = VERSION_BCD(02.00),
51 + .Class = USB_CSCP_IADDeviceClass,
52 + .SubClass = USB_CSCP_IADDeviceSubclass,
53 + .Protocol = USB_CSCP_IADDeviceProtocol,
54 54
7. Made other VCP works in main loop.
In src\VirtualSerial\VirtualSerial.c
87 150
88 151
void VCOM_echo(void)
89 152
{
90 - if(CDC_Device_BytesReceived(&VirtualSerial_CDC_Interface))
153 + if(CDC_Device_BytesReceived(&VirtualSerial_CDC1_Interface))
91 154
{
92 - in_buff[0]
= CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
93 - CDC_Device_SendData(&VirtualSerial_CDC_Interface,
(char *)in_buff, 1);
155 + in_buff[0]
= CDC_Device_ReceiveByte(&VirtualSerial_CDC1_Interface);
156 + CDC_Device_SendData(&VirtualSerial_CDC1_Interface,
(char *)in_buff, 1);
94 157
Endpoint_ClearIN();
95 158
}
159 +#if
(DUAL_VCP_ENABLE || TRI_VCP_ENABLE)
160 + if(CDC_Device_BytesReceived(&VirtualSerial_CDC2_Interface))
161 + {
162 + in2_buff[0]
= CDC_Device_ReceiveByte(&VirtualSerial_CDC2_Interface);
163 + CDC_Device_SendData(&VirtualSerial_CDC2_Interface,
(char *)in2_buff, 1);
164 + Endpoint_ClearIN();
165 + }
166 +#endif
167 +#if
(TRI_VCP_ENABLE)
168 +
if(CDC_Device_BytesReceived(&VirtualSerial_CDC3_Interface))
169 + {
170 + in3_buff[0] =
CDC_Device_ReceiveByte(&VirtualSerial_CDC3_Interface);
171 +
CDC_Device_SendData(&VirtualSerial_CDC3_Interface, (char *)in3_buff,
1);
172 + Endpoint_ClearIN();
173 + }
174 +#endif
96 175
}
8. Fix defect on handling zero package issue.
In
src\LUFA\Drivers\USB\Core\SIM3u\EndpointStream_SIM3U.c
... ... @@
-265,6 +265,13 @@ uint8_t Endpoint_Write_Stream_LE(const void* const Buffer,
265 265
{
266 266
count
= USB0_EP0_write_fifo(buf, Length);
267 267
}
268 + if(Length
== ENDPOINT_CONTROLEP_DEFAULT_SIZE)
269 + {
270 + SI32_USB_A_set_in_packet_ready_ep0(SI32_USB_0);
271 + if
((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
272 + return ErrorCode;
273 + SI32_USB_A_set_in_packet_ready_ep0(SI32_USB_0);
274 + }
9. Fixed usb_ep_selected defect in USB ISR.
In
src\LUFA\Drivers\USB\Core\SIM3u\USBInterrupt_SIM3U.c
... ... @@
-103,7 +103,7 @@ void USB0_IRQHandler(void)
103 103
USB0_ep0_handler();
104 104
return;
105 105 }
106 -
106 + uint32_t ep_selected_backup =
usb_ep_selected;
107 107 if (usbEpInterruptMask &
(SI32_USB_A_IOINT_IN1I_MASK | SI32_USB_A_IOINT_OUT1I_MASK))
108 108 {
109 109
Endpoint_SelectEndpoint(1);
... ... @@
-124,7 +124,7 @@ void USB0_IRQHandler(void)
124 124
Endpoint_SelectEndpoint(4);
125 125
USB0_epn_handler();
126 126 }
127 -
127 + usb_ep_selected = ep_selected_backup;
128 128 // Handle Start of Frame Interrupt
10.
Source code
No comments:
Post a Comment