Cleanups to RNDIS device demos. Fix issue in RNDIS demos where the memory would become corrupted due to an incorrect bounds check when iterating over the port state table, causing random resets.

Revert change to Template_Endpoint_Control_R.c, which broke control stream reads.

Remove uneeded ADC.h include in the class driver AudioOutput demo.
pull/1469/head
Dean Camera 15 years ago
parent 85c2716f2d
commit d423090b26

@ -47,7 +47,6 @@
#include <LUFA/Version.h> #include <LUFA/Version.h>
#include <LUFA/Drivers/Board/LEDs.h> #include <LUFA/Drivers/Board/LEDs.h>
#include <LUFA/Drivers/Board/Joystick.h> #include <LUFA/Drivers/Board/Joystick.h>
#include <LUFA/Drivers/Peripheral/ADC.h>
#include <LUFA/Drivers/USB/USB.h> #include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Drivers/USB/Class/Audio.h> #include <LUFA/Drivers/USB/Class/Audio.h>

@ -59,7 +59,7 @@ const IP_Address_t ClientIPAddress = {CLIENT_IP_ADDRESS};
*/ */
void Ethernet_ProcessPacket(Ethernet_Frame_Info_t* FrameIN, Ethernet_Frame_Info_t* FrameOUT) void Ethernet_ProcessPacket(Ethernet_Frame_Info_t* FrameIN, Ethernet_Frame_Info_t* FrameOUT)
{ {
DecodeEthernetFrameHeader(FrameIN->FrameData); DecodeEthernetFrameHeader(FrameIN);
/* Cast the incoming Ethernet frame to the Ethernet header type */ /* Cast the incoming Ethernet frame to the Ethernet header type */
Ethernet_Frame_Header_t* FrameINHeader = (Ethernet_Frame_Header_t*)&FrameIN->FrameData; Ethernet_Frame_Header_t* FrameINHeader = (Ethernet_Frame_Header_t*)&FrameIN->FrameData;
@ -69,7 +69,8 @@ void Ethernet_ProcessPacket(Ethernet_Frame_Info_t* FrameIN, Ethernet_Frame_Info_
/* Ensure frame is addressed to either all (broadcast) or the virtual webserver, and is a type II frame */ /* Ensure frame is addressed to either all (broadcast) or the virtual webserver, and is a type II frame */
if ((MAC_COMPARE(&FrameINHeader->Destination, &ServerMACAddress) || if ((MAC_COMPARE(&FrameINHeader->Destination, &ServerMACAddress) ||
MAC_COMPARE(&FrameINHeader->Destination, &BroadcastMACAddress))) MAC_COMPARE(&FrameINHeader->Destination, &BroadcastMACAddress)) &&
(SwapEndian_16(FrameIN->FrameLength) > ETHERNET_VER2_MINSIZE))
{ {
/* Process the packet depending on its protocol */ /* Process the packet depending on its protocol */
switch (SwapEndian_16(FrameINHeader->EtherType)) switch (SwapEndian_16(FrameINHeader->EtherType))

@ -53,7 +53,7 @@
/* Macros: */ /* Macros: */
/** Physical MAC address of the USB RNDIS network adapter */ /** Physical MAC address of the USB RNDIS network adapter */
#define ADAPTER_MAC_ADDRESS {0x00, 0x02, 0x00, 0x02, 0x00, 0x02} #define ADAPTER_MAC_ADDRESS {0x02, 0x00, 0x02, 0x00, 0x02, 0x00}
/** Physical MAC address of the virtual server on the network */ /** Physical MAC address of the virtual server on the network */
#define SERVER_MAC_ADDRESS {0x00, 0x01, 0x00, 0x01, 0x00, 0x01} #define SERVER_MAC_ADDRESS {0x00, 0x01, 0x00, 0x01, 0x00, 0x01}
@ -70,6 +70,9 @@
*/ */
#define MAC_COMPARE(MAC1, MAC2) (memcmp(MAC1, MAC2, sizeof(MAC_Address_t)) == 0) #define MAC_COMPARE(MAC1, MAC2) (memcmp(MAC1, MAC2, sizeof(MAC_Address_t)) == 0)
/** Minimum size of an Ethernet packet in bytes, to conform to the Ethernet V2 packet standard */
#define ETHERNET_VER2_MINSIZE 0x0600
/** Return value for all sub protocol handling routines, indicating that no response packet has been generated */ /** Return value for all sub protocol handling routines, indicating that no response packet has been generated */
#define NO_RESPONSE 0 #define NO_RESPONSE 0

@ -53,15 +53,15 @@
* *
* \param[in] InDataStart Pointer to the start of an Ethernet frame header * \param[in] InDataStart Pointer to the start of an Ethernet frame header
*/ */
void DecodeEthernetFrameHeader(void* InDataStart) void DecodeEthernetFrameHeader(Ethernet_Frame_Info_t* FrameINData)
{ {
#if !defined(NO_DECODE_ETHERNET) #if !defined(NO_DECODE_ETHERNET)
Ethernet_Frame_Header_t* FrameHeader = (Ethernet_Frame_Header_t*)InDataStart; Ethernet_Frame_Header_t* FrameHeader = (Ethernet_Frame_Header_t*)FrameINData->FrameData;
printf_P(PSTR("\r\n")); printf_P(PSTR("\r\n"));
printf_P(PSTR(" ETHERNET\r\n")); printf_P(PSTR(" ETHERNET\r\n"));
printf_P(PSTR(" + Frame Size: %u\r\n"), FrameIN.FrameLength); printf_P(PSTR(" + Frame Size: %u\r\n"), FrameINData->FrameLength);
if (!(MAC_COMPARE(&FrameHeader->Destination, &ServerMACAddress)) && if (!(MAC_COMPARE(&FrameHeader->Destination, &ServerMACAddress)) &&
!(MAC_COMPARE(&FrameHeader->Destination, &BroadcastMACAddress))) !(MAC_COMPARE(&FrameHeader->Destination, &BroadcastMACAddress)))
@ -84,7 +84,7 @@ void DecodeEthernetFrameHeader(void* InDataStart)
FrameHeader->Destination.Octets[4], FrameHeader->Destination.Octets[4],
FrameHeader->Destination.Octets[5]); FrameHeader->Destination.Octets[5]);
if (SwapEndian_16(FrameIN.FrameLength) > ETHERNET_VER2_MINSIZE) if (SwapEndian_16(FrameINData->FrameLength) > ETHERNET_VER2_MINSIZE)
printf_P(PSTR(" + Protocol: 0x%04x\r\n"), SwapEndian_16(FrameHeader->EtherType)); printf_P(PSTR(" + Protocol: 0x%04x\r\n"), SwapEndian_16(FrameHeader->EtherType));
else else
printf_P(PSTR(" + Protocol: UNKNOWN E1\r\n")); printf_P(PSTR(" + Protocol: UNKNOWN E1\r\n"));

@ -39,13 +39,14 @@
/* Includes: */ /* Includes: */
#include <avr/io.h> #include <avr/io.h>
#include <LUFA/Drivers/USB/Class/RNDIS.h>
#include <LUFA/Drivers/Peripheral/SerialStream.h> #include <LUFA/Drivers/Peripheral/SerialStream.h>
#include "EthernetProtocols.h" #include "EthernetProtocols.h"
#include "Ethernet.h" #include "Ethernet.h"
/* Function Prototypes: */ /* Function Prototypes: */
void DecodeEthernetFrameHeader(void* InDataStart); void DecodeEthernetFrameHeader(Ethernet_Frame_Info_t* FrameINData);
void DecodeARPHeader(void* InDataStart); void DecodeARPHeader(void* InDataStart);
void DecodeIPHeader(void* InDataStart); void DecodeIPHeader(void* InDataStart);
void DecodeICMPHeader(void* InDataStart); void DecodeICMPHeader(void* InDataStart);

@ -58,25 +58,27 @@ TCP_ConnectionState_t ConnectionStateTable[MAX_TCP_CONNECTIONS];
*/ */
void TCP_TCPTask(USB_ClassInfo_RNDIS_Device_t* RNDISInterfaceInfo) void TCP_TCPTask(USB_ClassInfo_RNDIS_Device_t* RNDISInterfaceInfo)
{ {
/* Task to hand off TCP packets to and from the listening applications. */
/* Run each application in sequence, to process incoming and generate outgoing packets */ /* Run each application in sequence, to process incoming and generate outgoing packets */
for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++) for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)
{ {
/* Find the corresponding port entry in the port table */ /* Find the corresponding port entry in the port table */
for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++) for (uint8_t PTableEntry = 0; PTableEntry < MAX_OPEN_TCP_PORTS; PTableEntry++)
{ {
/* Run the application handler for the port */ /* Run the application handler for the port */
if ((PortStateTable[PTableEntry].Port == ConnectionStateTable[CSTableEntry].Port) && if ((PortStateTable[PTableEntry].Port == ConnectionStateTable[CSTableEntry].Port) &&
(PortStateTable[PTableEntry].State == TCP_Port_Open)) (PortStateTable[PTableEntry].State == TCP_Port_Open))
{ {
PortStateTable[PTableEntry].ApplicationHandler(&ConnectionStateTable[CSTableEntry], &ConnectionStateTable[CSTableEntry].Info.Buffer); PortStateTable[PTableEntry].ApplicationHandler(&ConnectionStateTable[CSTableEntry],
&ConnectionStateTable[CSTableEntry].Info.Buffer);
} }
} }
} }
/* Get pointer to the output frame info struct for convenience */
Ethernet_Frame_Info_t* FrameOUT = (Ethernet_Frame_Info_t*)&RNDISInterfaceInfo->State.FrameOUT;
/* Bail out early if there is already a frame waiting to be sent in the Ethernet OUT buffer */ /* Bail out early if there is already a frame waiting to be sent in the Ethernet OUT buffer */
if (RNDISInterfaceInfo->State.FrameOUT.FrameInBuffer) if (FrameOUT->FrameInBuffer)
return; return;
/* Send response packets from each application as the TCP packet buffers are filled by the applications */ /* Send response packets from each application as the TCP packet buffers are filled by the applications */
@ -86,11 +88,11 @@ void TCP_TCPTask(USB_ClassInfo_RNDIS_Device_t* RNDISInterfaceInfo)
if ((ConnectionStateTable[CSTableEntry].Info.Buffer.Direction == TCP_PACKETDIR_OUT) && if ((ConnectionStateTable[CSTableEntry].Info.Buffer.Direction == TCP_PACKETDIR_OUT) &&
(ConnectionStateTable[CSTableEntry].Info.Buffer.Ready)) (ConnectionStateTable[CSTableEntry].Info.Buffer.Ready))
{ {
Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&RNDISInterfaceInfo->State.FrameOUT.FrameData; Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&FrameOUT->FrameData;
IP_Header_t* IPHeaderOUT = (IP_Header_t*)&RNDISInterfaceInfo->State.FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)]; IP_Header_t* IPHeaderOUT = (IP_Header_t*)&FrameOUT->FrameData[sizeof(Ethernet_Frame_Header_t)];
TCP_Header_t* TCPHeaderOUT = (TCP_Header_t*)&RNDISInterfaceInfo->State.FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t) + TCP_Header_t* TCPHeaderOUT = (TCP_Header_t*)&FrameOUT->FrameData[sizeof(Ethernet_Frame_Header_t) +
sizeof(IP_Header_t)]; sizeof(IP_Header_t)];
void* TCPDataOUT = &RNDISInterfaceInfo->State.FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t) + void* TCPDataOUT = &FrameOUT->FrameData[sizeof(Ethernet_Frame_Header_t) +
sizeof(IP_Header_t) + sizeof(IP_Header_t) +
sizeof(TCP_Header_t)]; sizeof(TCP_Header_t)];
@ -145,8 +147,8 @@ void TCP_TCPTask(USB_ClassInfo_RNDIS_Device_t* RNDISInterfaceInfo)
PacketSize += sizeof(Ethernet_Frame_Header_t); PacketSize += sizeof(Ethernet_Frame_Header_t);
/* Set the response length in the buffer and indicate that a response is ready to be sent */ /* Set the response length in the buffer and indicate that a response is ready to be sent */
RNDISInterfaceInfo->State.FrameOUT.FrameLength = PacketSize; FrameOUT->FrameLength = PacketSize;
RNDISInterfaceInfo->State.FrameOUT.FrameInBuffer = true; FrameOUT->FrameInBuffer = true;
ConnectionStateTable[CSTableEntry].Info.Buffer.Ready = false; ConnectionStateTable[CSTableEntry].Info.Buffer.Ready = false;
@ -366,12 +368,13 @@ int16_t TCP_ProcessTCPPacket(void* IPHeaderInStart, void* TCPHeaderInStart, void
/* Detect RST from host to abort existing connection */ /* Detect RST from host to abort existing connection */
if (TCPHeaderIN->Flags & TCP_FLAG_RST) if (TCPHeaderIN->Flags & TCP_FLAG_RST)
{
if (TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,
TCPHeaderIN->SourcePort, TCP_Connection_Closed))
{ {
TCPHeaderOUT->Flags = (TCP_FLAG_RST | TCP_FLAG_ACK); TCPHeaderOUT->Flags = (TCP_FLAG_RST | TCP_FLAG_ACK);
PacketResponse = true; PacketResponse = true;
}
TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,
TCPHeaderIN->SourcePort, TCP_Connection_Closed);
} }
else else
{ {

@ -55,12 +55,13 @@ int16_t UDP_ProcessUDPPacket(void* IPHeaderInStart, void* UDPHeaderInStart, void
DecodeUDPHeader(UDPHeaderInStart); DecodeUDPHeader(UDPHeaderInStart);
/* Check to see if the UDP packet is a DHCP packet */ switch (SwapEndian_16(UDPHeaderIN->DestinationPort))
if (SwapEndian_16(UDPHeaderIN->DestinationPort) == UDP_PORT_DHCP_REQUEST)
{ {
case UDP_PORT_DHCP_REQUEST:
RetSize = DHCP_ProcessDHCPPacket(IPHeaderInStart, RetSize = DHCP_ProcessDHCPPacket(IPHeaderInStart,
&((uint8_t*)UDPHeaderInStart)[sizeof(UDP_Header_t)], &((uint8_t*)UDPHeaderInStart)[sizeof(UDP_Header_t)],
&((uint8_t*)UDPHeaderOutStart)[sizeof(UDP_Header_t)]); &((uint8_t*)UDPHeaderOutStart)[sizeof(UDP_Header_t)]);
break;
} }
/* Check to see if the protocol processing routine has filled out a response */ /* Check to see if the protocol processing routine has filled out a response */

@ -42,6 +42,7 @@
#include "EthernetProtocols.h" #include "EthernetProtocols.h"
#include "Ethernet.h" #include "Ethernet.h"
#include "ProtocolDecoders.h" #include "ProtocolDecoders.h"
#include "DHCP.h"
/* Macros: */ /* Macros: */
/** Source UDP port for a DHCP request */ /** Source UDP port for a DHCP request */

@ -202,7 +202,8 @@ CSTANDARD = -std=gnu99
# Place -D or -U options here for C sources # Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD) $(LUFA_OPTS) CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD) $(LUFA_OPTS)
CDEFS += -DNO_DECODE_ETHERNET -DNO_DECODE_ARP -DNO_DECODE_ICMP -DNO_DECODE_IP -DNO_DECODE_TCP -DNO_DECODE_UDP -DNO_DECODE_DHCP CDEFS += -DNO_DECODE_ETHERNET -DNO_DECODE_ARP -DNO_DECODE_ICMP
CDEFS += -DNO_DECODE_IP -DNO_DECODE_TCP -DNO_DECODE_UDP -DNO_DECODE_DHCP -DNO_DECODE_DNS
# Place -D or -U options here for ASM sources # Place -D or -U options here for ASM sources

@ -50,6 +50,9 @@
#include "IP.h" #include "IP.h"
/* Macros: */ /* Macros: */
/** Physical MAC address of the USB RNDIS network adapter */
#define ADAPTER_MAC_ADDRESS {0x02, 0x00, 0x02, 0x00, 0x02, 0x00}
/** Physical MAC address of the virtual server on the network */ /** Physical MAC address of the virtual server on the network */
#define SERVER_MAC_ADDRESS {0x00, 0x01, 0x00, 0x01, 0x00, 0x01} #define SERVER_MAC_ADDRESS {0x00, 0x01, 0x00, 0x01, 0x00, 0x01}

@ -275,6 +275,5 @@ void DecodeDHCPHeader(void* InDataStart)
DHCPOptions += ((DHCPOptions[0] == DHCP_OPTION_PAD) ? 1 : (DHCPOptions[1] + 2)); DHCPOptions += ((DHCPOptions[0] == DHCP_OPTION_PAD) ? 1 : (DHCPOptions[1] + 2));
} }
#endif #endif
} }

@ -45,9 +45,6 @@
#include "Ethernet.h" #include "Ethernet.h"
/* Macros: */ /* Macros: */
/** Physical MAC Address of the USB network adapter */
#define ADAPTER_MAC_ADDRESS {0x02, 0x00, 0x02, 0x00, 0x02, 0x00}
/** Implemented RNDIS Version Major */ /** Implemented RNDIS Version Major */
#define REMOTE_NDIS_VERSION_MAJOR 0x01 #define REMOTE_NDIS_VERSION_MAJOR 0x01

@ -58,19 +58,18 @@ TCP_ConnectionState_t ConnectionStateTable[MAX_TCP_CONNECTIONS];
*/ */
void TCP_Task(void) void TCP_Task(void)
{ {
/* Task to hand off TCP packets to and from the listening applications. */
/* Run each application in sequence, to process incoming and generate outgoing packets */ /* Run each application in sequence, to process incoming and generate outgoing packets */
for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++) for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)
{ {
/* Find the corresponding port entry in the port table */ /* Find the corresponding port entry in the port table */
for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++) for (uint8_t PTableEntry = 0; PTableEntry < MAX_OPEN_TCP_PORTS; PTableEntry++)
{ {
/* Run the application handler for the port */ /* Run the application handler for the port */
if ((PortStateTable[PTableEntry].Port == ConnectionStateTable[CSTableEntry].Port) && if ((PortStateTable[PTableEntry].Port == ConnectionStateTable[CSTableEntry].Port) &&
(PortStateTable[PTableEntry].State == TCP_Port_Open)) (PortStateTable[PTableEntry].State == TCP_Port_Open))
{ {
PortStateTable[PTableEntry].ApplicationHandler(&ConnectionStateTable[CSTableEntry], &ConnectionStateTable[CSTableEntry].Info.Buffer); PortStateTable[PTableEntry].ApplicationHandler(&ConnectionStateTable[CSTableEntry],
&ConnectionStateTable[CSTableEntry].Info.Buffer);
} }
} }
} }
@ -366,12 +365,13 @@ int16_t TCP_ProcessTCPPacket(void* IPHeaderInStart, void* TCPHeaderInStart, void
/* Detect RST from host to abort existing connection */ /* Detect RST from host to abort existing connection */
if (TCPHeaderIN->Flags & TCP_FLAG_RST) if (TCPHeaderIN->Flags & TCP_FLAG_RST)
{
if (TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,
TCPHeaderIN->SourcePort, TCP_Connection_Closed))
{ {
TCPHeaderOUT->Flags = (TCP_FLAG_RST | TCP_FLAG_ACK); TCPHeaderOUT->Flags = (TCP_FLAG_RST | TCP_FLAG_ACK);
PacketResponse = true; PacketResponse = true;
}
TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,
TCPHeaderIN->SourcePort, TCP_Connection_Closed);
} }
else else
{ {

@ -55,12 +55,13 @@ int16_t UDP_ProcessUDPPacket(void* IPHeaderInStart, void* UDPHeaderInStart, void
DecodeUDPHeader(UDPHeaderInStart); DecodeUDPHeader(UDPHeaderInStart);
/* Check to see if the UDP packet is a DHCP packet */ switch (SwapEndian_16(UDPHeaderIN->DestinationPort))
if (SwapEndian_16(UDPHeaderIN->DestinationPort) == UDP_PORT_DHCP_REQUEST)
{ {
case UDP_PORT_DHCP_REQUEST:
RetSize = DHCP_ProcessDHCPPacket(IPHeaderInStart, RetSize = DHCP_ProcessDHCPPacket(IPHeaderInStart,
&((uint8_t*)UDPHeaderInStart)[sizeof(UDP_Header_t)], &((uint8_t*)UDPHeaderInStart)[sizeof(UDP_Header_t)],
&((uint8_t*)UDPHeaderOutStart)[sizeof(UDP_Header_t)]); &((uint8_t*)UDPHeaderOutStart)[sizeof(UDP_Header_t)]);
break;
} }
/* Check to see if the protocol processing routine has filled out a response */ /* Check to see if the protocol processing routine has filled out a response */

@ -42,6 +42,7 @@
#include "EthernetProtocols.h" #include "EthernetProtocols.h"
#include "Ethernet.h" #include "Ethernet.h"
#include "ProtocolDecoders.h" #include "ProtocolDecoders.h"
#include "DHCP.h"
/* Macros: */ /* Macros: */
/** Source UDP port for a DHCP request */ /** Source UDP port for a DHCP request */
@ -50,6 +51,9 @@
/** Destination UDP port for a DHCP reply */ /** Destination UDP port for a DHCP reply */
#define UDP_PORT_DHCP_REPLY 68 #define UDP_PORT_DHCP_REPLY 68
/** Source UDP port for a DNS request/response */
#define UDP_PORT_DNS 53
/* Type Defines: */ /* Type Defines: */
/** Type define for a UDP packet header */ /** Type define for a UDP packet header */
typedef struct typedef struct

@ -1,12 +1,8 @@
uint8_t TEMPLATE_FUNC_NAME (void* Buffer, uint16_t Length) uint8_t TEMPLATE_FUNC_NAME (void* Buffer, uint16_t Length)
{ {
uint8_t* DataStream = (uint8_t*)(Buffer + TEMPLATE_BUFFER_OFFSET(Length)); uint8_t* DataStream = (uint8_t*)(Buffer + TEMPLATE_BUFFER_OFFSET(Length));
bool LastPacketFull = false;
if (Length > USB_ControlRequest.wLength) while (Length)
Length = USB_ControlRequest.wLength;
while (Length || LastPacketFull)
{ {
if (Endpoint_IsSETUPReceived()) if (Endpoint_IsSETUPReceived())
return ENDPOINT_RWCSTREAM_HostAborted; return ENDPOINT_RWCSTREAM_HostAborted;
@ -16,8 +12,6 @@ uint8_t TEMPLATE_FUNC_NAME (void* Buffer, uint16_t Length)
if (Endpoint_IsOUTReceived()) if (Endpoint_IsOUTReceived())
{ {
LastPacketFull = (Endpoint_BytesInEndpoint() == USB_ControlEndpointSize);
while (Length && Endpoint_BytesInEndpoint()) while (Length && Endpoint_BytesInEndpoint())
{ {
TEMPLATE_TRANSFER_BYTE(DataStream); TEMPLATE_TRANSFER_BYTE(DataStream);
@ -25,9 +19,6 @@ uint8_t TEMPLATE_FUNC_NAME (void* Buffer, uint16_t Length)
} }
Endpoint_ClearOUT(); Endpoint_ClearOUT();
if (!(LastPacketFull))
Length = 0;
} }
} }

Loading…
Cancel
Save