Added new RNDISHost Host LowLevel demo. Fixed misnamed Pipe_SetPipeToken() macro for setting a pipe's direction. Fixed CDCHost failing on devices with bidirectional endpoints.

This commit is contained in:
Dean Camera 2009-11-25 03:26:57 +00:00
parent c05c7c7df4
commit 8c6c27d88b
26 changed files with 1746 additions and 76 deletions

View File

@ -216,8 +216,9 @@ void CDC_Host_Task(void)
USB_HostState = HOST_STATE_Configured; USB_HostState = HOST_STATE_Configured;
break; break;
case HOST_STATE_Configured: case HOST_STATE_Configured:
/* Select and the data IN pipe */ /* Select the data IN pipe */
Pipe_SelectPipe(CDC_DATAPIPE_IN); Pipe_SelectPipe(CDC_DATAPIPE_IN);
Pipe_SetPipeToken(PIPE_TOKEN_IN);
Pipe_Unfreeze(); Pipe_Unfreeze();
/* Check to see if a packet has been received */ /* Check to see if a packet has been received */

View File

@ -145,6 +145,10 @@ uint8_t ProcessConfigurationDescriptor(void)
/* Check if the endpoint is a bulk IN or bulk OUT endpoint */ /* Check if the endpoint is a bulk IN or bulk OUT endpoint */
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
{ {
/* Kill the configured OUT pipe if the data endpoints are bidirectional */
if (Pipe_IsEndpointBound(EndpointData->EndpointAddress))
Pipe_DisablePipe();
/* Configure the data IN pipe */ /* Configure the data IN pipe */
Pipe_ConfigurePipe(CDC_DATAPIPE_IN, EP_TYPE_BULK, PIPE_TOKEN_IN, Pipe_ConfigurePipe(CDC_DATAPIPE_IN, EP_TYPE_BULK, PIPE_TOKEN_IN,
EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE);
@ -154,9 +158,13 @@ uint8_t ProcessConfigurationDescriptor(void)
} }
else else
{ {
/* Configure the data OUT pipe */ /* Only configure the OUT data pipe if the data endpoints haev not shown to be bidirectional */
Pipe_ConfigurePipe(CDC_DATAPIPE_OUT, EP_TYPE_BULK, PIPE_TOKEN_OUT, if (!(Pipe_IsEndpointBound(EndpointData->EndpointAddress)))
EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); {
/* Configure the data OUT pipe */
Pipe_ConfigurePipe(CDC_DATAPIPE_OUT, EP_TYPE_BULK, PIPE_TOKEN_OUT,
EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE);
}
/* Set the flag indicating that the data OUT pipe has been found */ /* Set the flag indicating that the data OUT pipe has been found */
FoundEndpoints |= (1 << CDC_DATAPIPE_OUT); FoundEndpoints |= (1 << CDC_DATAPIPE_OUT);

View File

@ -145,6 +145,10 @@ uint8_t ProcessConfigurationDescriptor(void)
/* Check if the endpoint is a bulk IN or bulk OUT endpoint */ /* Check if the endpoint is a bulk IN or bulk OUT endpoint */
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
{ {
/* Kill the configured OUT pipe if the data endpoints are bidirectional */
if (Pipe_IsEndpointBound(EndpointData->EndpointAddress))
Pipe_DisablePipe();
/* Configure the data IN pipe */ /* Configure the data IN pipe */
Pipe_ConfigurePipe(RNDIS_DATAPIPE_IN, EP_TYPE_BULK, PIPE_TOKEN_IN, Pipe_ConfigurePipe(RNDIS_DATAPIPE_IN, EP_TYPE_BULK, PIPE_TOKEN_IN,
EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE);
@ -154,9 +158,13 @@ uint8_t ProcessConfigurationDescriptor(void)
} }
else else
{ {
/* Configure the data OUT pipe */ /* Only configure the OUT data pipe if the data endpoints haev not shown to be bidirectional */
Pipe_ConfigurePipe(RNDIS_DATAPIPE_OUT, EP_TYPE_BULK, PIPE_TOKEN_OUT, if (!(Pipe_IsEndpointBound(EndpointData->EndpointAddress)))
EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); {
/* Configure the data OUT pipe */
Pipe_ConfigurePipe(RNDIS_DATAPIPE_OUT, EP_TYPE_BULK, PIPE_TOKEN_OUT,
EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE);
}
/* Set the flag indicating that the data OUT pipe has been found */ /* Set the flag indicating that the data OUT pipe has been found */
FoundEndpoints |= (1 << RNDIS_DATAPIPE_OUT); FoundEndpoints |= (1 << RNDIS_DATAPIPE_OUT);

File diff suppressed because it is too large Load Diff

View File

@ -30,14 +30,23 @@
/** \file /** \file
* *
* RNDOS Device commands, to issue RNDIS commands to the device for * RNDIS Device commands, to issue RNDIS commands to the device for
* the control and data transfer between the host and RNDIS device. * the control and data transfer between the host and RNDIS device.
*/ */
#include "RNDISCommands.h" #include "RNDISCommands.h"
/** Current RNDIS Request ID, for associating sent commands with received data */
uint32_t RequestID = 0; uint32_t RequestID = 0;
/** Function to send the given encapsulated RNDIS command to the device.
*
* \param[in] Buffer Source command data buffer to send to the device
* \param[in] Bytes Number of bytes to send
*
* \return A value from the USB_Host_SendControlErrorCodes_t enum
*/
uint8_t RNDIS_SendEncapsulatedCommand(void* Buffer, uint16_t Length) uint8_t RNDIS_SendEncapsulatedCommand(void* Buffer, uint16_t Length)
{ {
USB_ControlRequest = (USB_Request_Header_t) USB_ControlRequest = (USB_Request_Header_t)
@ -55,6 +64,13 @@ uint8_t RNDIS_SendEncapsulatedCommand(void* Buffer, uint16_t Length)
return USB_Host_SendControlRequest(Buffer); return USB_Host_SendControlRequest(Buffer);
} }
/** Function to receive the given encapsulated RNDIS response from the device.
*
* \param[out] Buffer Destination command data buffer to write read data from the device to
* \param[in] Bytes Number of bytes to read
*
* \return A value from the USB_Host_SendControlErrorCodes_t enum
*/
uint8_t RNDIS_GetEncapsulatedResponse(void* Buffer, uint16_t Length) uint8_t RNDIS_GetEncapsulatedResponse(void* Buffer, uint16_t Length)
{ {
USB_ControlRequest = (USB_Request_Header_t) USB_ControlRequest = (USB_Request_Header_t)
@ -72,6 +88,11 @@ uint8_t RNDIS_GetEncapsulatedResponse(void* Buffer, uint16_t Length)
return USB_Host_SendControlRequest(Buffer); return USB_Host_SendControlRequest(Buffer);
} }
/** Sends a RNDIS KEEPALIVE command to the device, to ensure that it does not enter standby mode after periods
* of long inactivity.
*
* \return A value from the USB_Host_SendControlErrorCodes_t enum
*/
uint8_t RNDIS_SendKeepAlive(void) uint8_t RNDIS_SendKeepAlive(void)
{ {
uint8_t ErrorCode; uint8_t ErrorCode;
@ -98,6 +119,13 @@ uint8_t RNDIS_SendKeepAlive(void)
return HOST_SENDCONTROL_Successful; return HOST_SENDCONTROL_Successful;
} }
/** Initializes the attached RNDIS device's RNDIS interface.
*
* \param[in] HostMaxPacketSize Size of the packet buffer on the host
* \param[out] DeviceMaxPacketSize Pointer to where the packet buffer size of the device is to be stored
*
* \return A value from the USB_Host_SendControlErrorCodes_t enum
*/
uint8_t RNDIS_InitializeDevice(uint16_t HostMaxPacketSize, uint16_t* DeviceMaxPacketSize) uint8_t RNDIS_InitializeDevice(uint16_t HostMaxPacketSize, uint16_t* DeviceMaxPacketSize)
{ {
uint8_t ErrorCode; uint8_t ErrorCode;
@ -133,6 +161,14 @@ uint8_t RNDIS_InitializeDevice(uint16_t HostMaxPacketSize, uint16_t* DeviceMaxPa
return HOST_SENDCONTROL_Successful; return HOST_SENDCONTROL_Successful;
} }
/** Sets a given RNDIS property of an attached RNDIS device.
*
* \param[in] Oid OID number of the parameter to set
* \param[in] Buffer Pointer to where the property data is to be sourced from
* \param[in] Length Length in bytes of the property data to sent to the device
*
* \return A value from the USB_Host_SendControlErrorCodes_t enum
*/
uint8_t RNDIS_SetRNDISProperty(uint32_t Oid, void* Buffer, uint16_t Length) uint8_t RNDIS_SetRNDISProperty(uint32_t Oid, void* Buffer, uint16_t Length)
{ {
uint8_t ErrorCode; uint8_t ErrorCode;
@ -174,6 +210,14 @@ uint8_t RNDIS_SetRNDISProperty(uint32_t Oid, void* Buffer, uint16_t Length)
return HOST_SENDCONTROL_Successful; return HOST_SENDCONTROL_Successful;
} }
/** Gets a given RNDIS property of an attached RNDIS device.
*
* \param[in] Oid OID number of the parameter to get
* \param[in] Buffer Pointer to where the property data is to be written to
* \param[in] MaxLength Length in bytes of the destination buffer size
*
* \return A value from the USB_Host_SendControlErrorCodes_t enum
*/
uint8_t RNDIS_QueryRNDISProperty(uint32_t Oid, void* Buffer, uint16_t MaxLength) uint8_t RNDIS_QueryRNDISProperty(uint32_t Oid, void* Buffer, uint16_t MaxLength)
{ {
uint8_t ErrorCode; uint8_t ErrorCode;
@ -215,10 +259,28 @@ uint8_t RNDIS_QueryRNDISProperty(uint32_t Oid, void* Buffer, uint16_t MaxLength)
return HOST_SENDCONTROL_Successful; return HOST_SENDCONTROL_Successful;
} }
/** Retrieves the size of a received packet, discarding the remainder of the RNDIS packet header to leave only the
* packet contents for processing by the host.
*
* \param[out] PacketLength Size of the packet currently in the pipe
*
* \return A value from the Pipe_Stream_RW_ErrorCodes_t enum
*/
uint8_t RNDIS_GetPacketLength(uint16_t* PacketLength) uint8_t RNDIS_GetPacketLength(uint16_t* PacketLength)
{ {
uint8_t ErrorCode; uint8_t ErrorCode;
Pipe_SelectPipe(RNDIS_DATAPIPE_IN);
Pipe_SetPipeToken(PIPE_TOKEN_IN);
Pipe_Unfreeze();
if (!(Pipe_IsReadWriteAllowed()))
{
*PacketLength = 0;
Pipe_Freeze();
return PIPE_RWSTREAM_NoError;
}
RNDIS_Packet_Message_t DeviceMessage; RNDIS_Packet_Message_t DeviceMessage;
if ((ErrorCode = Pipe_Read_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t))) != PIPE_RWSTREAM_NoError) if ((ErrorCode = Pipe_Read_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t))) != PIPE_RWSTREAM_NoError)
@ -230,5 +292,7 @@ uint8_t RNDIS_GetPacketLength(uint16_t* PacketLength)
Pipe_Discard_Stream(DeviceMessage.DataOffset - (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t))); Pipe_Discard_Stream(DeviceMessage.DataOffset - (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t)));
Pipe_Freeze();
return PIPE_RWSTREAM_NoError; return PIPE_RWSTREAM_NoError;
} }

View File

@ -125,19 +125,8 @@ void PrintIncommingPackets(void)
{ {
uint8_t ErrorCode; uint8_t ErrorCode;
Pipe_SelectPipe(RNDIS_DATAPIPE_IN);
Pipe_Unfreeze();
if (!(Pipe_IsReadWriteAllowed()))
{
Pipe_Freeze();
return;
}
LEDs_SetAllLEDs(LEDMASK_USB_BUSY); LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
puts_P(PSTR("DATA IN\r\n"));
uint16_t PacketLength; uint16_t PacketLength;
if ((ErrorCode = RNDIS_GetPacketLength(&PacketLength)) != HOST_SENDCONTROL_Successful) if ((ErrorCode = RNDIS_GetPacketLength(&PacketLength)) != HOST_SENDCONTROL_Successful)
{ {
@ -146,6 +135,11 @@ void PrintIncommingPackets(void)
return; return;
} }
if (!(PacketLength))
return;
Pipe_Unfreeze();
printf_P(PSTR("***PACKET (Size %d)***\r\n"), PacketLength); printf_P(PSTR("***PACKET (Size %d)***\r\n"), PacketLength);
if (PacketLength > 1024) if (PacketLength > 1024)
@ -163,12 +157,12 @@ void PrintIncommingPackets(void)
printf("%02x ", PacketBuffer[i]); printf("%02x ", PacketBuffer[i]);
} }
Pipe_ClearIN();
Pipe_Freeze();
printf("\r\n\r\n"); printf("\r\n\r\n");
LEDs_SetAllLEDs(LEDMASK_USB_READY); LEDs_SetAllLEDs(LEDMASK_USB_READY);
Pipe_ClearIN();
Pipe_Freeze();
} }
/** Task to set the configuration of the attached device after it has been enumerated, and to read in /** Task to set the configuration of the attached device after it has been enumerated, and to read in
@ -247,24 +241,6 @@ void RNDIS_Host_Task(void)
break; break;
} }
uint32_t RetrievedPacketFilter;
if ((ErrorCode = RNDIS_QueryRNDISProperty(OID_GEN_CURRENT_PACKET_FILTER,
&RetrievedPacketFilter, sizeof(RetrievedPacketFilter))) != HOST_SENDCONTROL_Successful)
{
printf_P(PSTR(ESC_FG_RED "Error Getting Packet Filter.\r\n"
" -- Error Code: %d\r\n" ESC_FG_WHITE), ErrorCode);
/* Indicate error via status LEDs */
LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
/* Wait until USB device disconnected */
USB_HostState = HOST_STATE_WaitForDeviceRemoval;
break;
}
if (RetrievedPacketFilter != PacketFilter)
printf("ERROR: Retrieved Packet Filter 0x%08lx != Set Packet Filter 0x%08lx!\r\n", RetrievedPacketFilter, PacketFilter);
uint32_t VendorID; uint32_t VendorID;
if ((ErrorCode = RNDIS_QueryRNDISProperty(OID_GEN_VENDOR_ID, if ((ErrorCode = RNDIS_QueryRNDISProperty(OID_GEN_VENDOR_ID,
&VendorID, sizeof(VendorID))) != HOST_SENDCONTROL_Successful) &VendorID, sizeof(VendorID))) != HOST_SENDCONTROL_Successful)

View File

@ -0,0 +1,62 @@
/** \file
*
* This file contains special DoxyGen information for the generation of the main page and other special
* documentation pages. It is not a project source file.
*/
/** \mainpage RNDIS Host Demo
*
* \section SSec_Compat Demo Compatibility:
*
* The following list indicates what microcontrollers are compatible with this demo.
*
* - Series 7 USB AVRs
*
* \section SSec_Info USB Information:
*
* The following table gives a rundown of the USB utilization of this demo.
*
* <table>
* <tr>
* <td><b>USB Mode:</b></td>
* <td>Host</td>
* </tr>
* <tr>
* <td><b>USB Class:</b></td>
* <td>Communications Device Class (CDC)</td>
* </tr>
* <tr>
* <td><b>USB Subclass:</b></td>
* <td>Remote NDIS (Microsoft Proprietary CDC Class Networking Standard)</td>
* </tr>
* <tr>
* <td><b>Relevant Standards:</b></td>
* <td>Microsoft RNDIS Specification</td>
* </tr>
* <tr>
* <td><b>Usable Speeds:</b></td>
* <td>Full Speed Mode</td>
* </tr>
* </table>
*
* \section SSec_Description Project Description:
*
* RNDIS host demonstration application. This gives a simple reference
* application for implementing a RNDIS Ethernet host, for USB devices such as
* modems.
*
* This demo will enumerate an attached USB RNDIS device, print out its vendor ID
* and any received packets in raw form through the serial USART.
*
* \section SSec_Options Project Options
*
* The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value.
*
* <table>
* <tr>
* <td>
* None
* </td>
* </tr>
* </table>
*/

View File

@ -78,7 +78,10 @@ void SImage_SendBlockHeader(void)
Pipe_Freeze(); Pipe_Freeze();
} }
/** Function to receive a PIMA event container from the attached still image device. */ /** Function to receive a PIMA event container from the attached still image device.
*
* \return A value from the Pipe_Stream_RW_ErrorCodes_t enum
/
uint8_t SImage_ReceiveEventHeader(void) uint8_t SImage_ReceiveEventHeader(void)
{ {
uint8_t ErrorCode; uint8_t ErrorCode;
@ -99,7 +102,10 @@ uint8_t SImage_ReceiveEventHeader(void)
return ErrorCode; return ErrorCode;
} }
/** Function to receive a PIMA response container from the attached still image device. */ /** Function to receive a PIMA response container from the attached still image device.
*
* \return A value from the Pipe_Stream_RW_ErrorCodes_t enum
*/
uint8_t SImage_ReceiveBlockHeader(void) uint8_t SImage_ReceiveBlockHeader(void)
{ {
uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS; uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS;
@ -189,6 +195,8 @@ uint8_t SImage_ReceiveBlockHeader(void)
* *
* \param[in] Buffer Source data buffer to send to the device * \param[in] Buffer Source data buffer to send to the device
* \param[in] Bytes Number of bytes to send * \param[in] Bytes Number of bytes to send
*
* \return A value from the Pipe_Stream_RW_ErrorCodes_t enum
*/ */
uint8_t SImage_SendData(void* Buffer, uint16_t Bytes) uint8_t SImage_SendData(void* Buffer, uint16_t Bytes)
{ {

View File

@ -44,6 +44,9 @@ all:
make -C StillImageHost clean make -C StillImageHost clean
make -C StillImageHost all make -C StillImageHost all
make -C RNDISHost clean
make -C RNDISHost all
%: %:
make -C CDCHost $@ make -C CDCHost $@
make -C GenericHIDHost $@ make -C GenericHIDHost $@
@ -56,3 +59,4 @@ all:
make -C MouseHostWithParser $@ make -C MouseHostWithParser $@
make -C PrinterHost $@ make -C PrinterHost $@
make -C StillImageHost $@ make -C StillImageHost $@
make -C RNDISHost $@

File diff suppressed because one or more lines are too long

View File

@ -110,18 +110,32 @@ uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo
{ {
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
{ {
if (Pipe_IsEndpointBound(EndpointData->EndpointAddress))
{
BidirectionalDataEndpoints = true;
Pipe_DisablePipe();
}
Pipe_ConfigurePipe(CDCInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN, Pipe_ConfigurePipe(CDCInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN,
EndpointData->EndpointAddress, EndpointData->EndpointSize, EndpointData->EndpointAddress, EndpointData->EndpointSize,
CDCInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); CDCInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
CDCInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize; CDCInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
FoundEndpoints |= CDC_FOUND_DATAPIPE_IN; FoundEndpoints |= CDC_FOUND_DATAPIPE_IN;
} }
else else
{ {
Pipe_ConfigurePipe(CDCInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT, if (Pipe_IsEndpointBound(EndpointData->EndpointAddress))
EndpointData->EndpointAddress, EndpointData->EndpointSize, {
CDCInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); BidirectionalDataEndpoints = true;
}
else
{
Pipe_ConfigurePipe(CDCInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT,
EndpointData->EndpointAddress, EndpointData->EndpointSize,
CDCInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
}
CDCInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize; CDCInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
FoundEndpoints |= CDC_FOUND_DATAPIPE_OUT; FoundEndpoints |= CDC_FOUND_DATAPIPE_OUT;
@ -180,8 +194,7 @@ static uint8_t DComp_CDC_Host_NextCDCInterfaceEndpoint(void* const CurrentDescri
uint8_t EndpointType = (CurrentEndpoint->Attributes & EP_TYPE_MASK); uint8_t EndpointType = (CurrentEndpoint->Attributes & EP_TYPE_MASK);
if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) && if ((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT))
!(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress)))
{ {
return DESCRIPTOR_SEARCH_Found; return DESCRIPTOR_SEARCH_Found;
} }
@ -200,6 +213,7 @@ void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
return; return;
Pipe_SelectPipe(CDCInterfaceInfo->Config.NotificationPipeNumber); Pipe_SelectPipe(CDCInterfaceInfo->Config.NotificationPipeNumber);
Pipe_SetPipeToken(PIPE_TOKEN_IN);
Pipe_Unfreeze(); Pipe_Unfreeze();
if (Pipe_IsINReceived()) if (Pipe_IsINReceived())
@ -263,11 +277,23 @@ uint8_t CDC_Host_SendString(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, ch
uint8_t ErrorCode; uint8_t ErrorCode;
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipeNumber); if (CDCInterfaceInfo->State.BidirectionalDataEndpoints)
{
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipeNumber);
Pipe_SetPipeToken(PIPE_TOKEN_IN);
}
else
{
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipeNumber);
}
Pipe_Unfreeze(); Pipe_Unfreeze();
ErrorCode = Pipe_Write_Stream_LE(Data, Length, NO_STREAM_CALLBACK); ErrorCode = Pipe_Write_Stream_LE(Data, Length, NO_STREAM_CALLBACK);
Pipe_Freeze(); Pipe_Freeze();
if (CDCInterfaceInfo->State.BidirectionalDataEndpoints)
Pipe_SetPipeToken(PIPE_TOKEN_IN);
return ErrorCode; return ErrorCode;
} }
@ -278,7 +304,16 @@ uint8_t CDC_Host_SendByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, cons
uint8_t ErrorCode; uint8_t ErrorCode;
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipeNumber); if (CDCInterfaceInfo->State.BidirectionalDataEndpoints)
{
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipeNumber);
Pipe_SetPipeToken(PIPE_TOKEN_IN);
}
else
{
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipeNumber);
}
Pipe_Unfreeze(); Pipe_Unfreeze();
if (!(Pipe_IsReadWriteAllowed())) if (!(Pipe_IsReadWriteAllowed()))
@ -292,6 +327,9 @@ uint8_t CDC_Host_SendByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, cons
Pipe_Write_Byte(Data); Pipe_Write_Byte(Data);
Pipe_Freeze(); Pipe_Freeze();
if (CDCInterfaceInfo->State.BidirectionalDataEndpoints)
Pipe_SetPipeToken(PIPE_TOKEN_IN);
return PIPE_READYWAIT_NoError; return PIPE_READYWAIT_NoError;
} }
@ -303,6 +341,7 @@ uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo
return BytesInPipe; return BytesInPipe;
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipeNumber); Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipeNumber);
Pipe_SetPipeToken(PIPE_TOKEN_IN);
Pipe_Unfreeze(); Pipe_Unfreeze();
if (Pipe_IsINReceived() && !(Pipe_BytesInPipe())) if (Pipe_IsINReceived() && !(Pipe_BytesInPipe()))
@ -322,6 +361,7 @@ uint8_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
return ReceivedByte; return ReceivedByte;
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipeNumber); Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipeNumber);
Pipe_SetPipeToken(PIPE_TOKEN_IN);
Pipe_Unfreeze(); Pipe_Unfreeze();
ReceivedByte = Pipe_Read_Byte(); ReceivedByte = Pipe_Read_Byte();

View File

@ -89,6 +89,11 @@
uint16_t DataOUTPipeSize; /**< Size in bytes of the CDC interface's OUT data pipe */ uint16_t DataOUTPipeSize; /**< Size in bytes of the CDC interface's OUT data pipe */
uint16_t NotificationPipeSize; /**< Size in bytes of the CDC interface's IN notification pipe, if used */ uint16_t NotificationPipeSize; /**< Size in bytes of the CDC interface's IN notification pipe, if used */
bool BidirectionalDataEndpoints; /**< Indicates if the attached CDC interface uses bidirectional data endpoints,
* and this has only the IN pipe configured (with \ref Pipe_SetPipeToken()
* used to switch the pipe's direction
*/
struct struct
{ {
uint8_t HostToDevice; /**< Control line states from the host to device, as a set of CDC_CONTROL_LINE_OUT_* uint8_t HostToDevice; /**< Control line states from the host to device, as a set of CDC_CONTROL_LINE_OUT_*

View File

@ -48,7 +48,7 @@ uint8_t USB_Host_SendControlRequest(void* BufferPtr)
if ((ReturnStatus = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful) if ((ReturnStatus = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful)
goto End_Of_Control_Send; goto End_Of_Control_Send;
Pipe_SetToken(PIPE_TOKEN_SETUP); Pipe_SetPipeToken(PIPE_TOKEN_SETUP);
Pipe_ClearErrorFlags(); Pipe_ClearErrorFlags();
Pipe_Unfreeze(); Pipe_Unfreeze();
@ -68,7 +68,7 @@ uint8_t USB_Host_SendControlRequest(void* BufferPtr)
if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_DIRECTION) == REQDIR_DEVICETOHOST) if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_DIRECTION) == REQDIR_DEVICETOHOST)
{ {
Pipe_SetToken(PIPE_TOKEN_IN); Pipe_SetPipeToken(PIPE_TOKEN_IN);
if (DataStream != NULL) if (DataStream != NULL)
{ {
@ -93,7 +93,7 @@ uint8_t USB_Host_SendControlRequest(void* BufferPtr)
} }
} }
Pipe_SetToken(PIPE_TOKEN_OUT); Pipe_SetPipeToken(PIPE_TOKEN_OUT);
Pipe_Unfreeze(); Pipe_Unfreeze();
if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful) if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful)
@ -108,7 +108,7 @@ uint8_t USB_Host_SendControlRequest(void* BufferPtr)
{ {
if (DataStream != NULL) if (DataStream != NULL)
{ {
Pipe_SetToken(PIPE_TOKEN_OUT); Pipe_SetPipeToken(PIPE_TOKEN_OUT);
Pipe_Unfreeze(); Pipe_Unfreeze();
while (DataLen) while (DataLen)
@ -131,7 +131,7 @@ uint8_t USB_Host_SendControlRequest(void* BufferPtr)
Pipe_Freeze(); Pipe_Freeze();
} }
Pipe_SetToken(PIPE_TOKEN_IN); Pipe_SetPipeToken(PIPE_TOKEN_IN);
Pipe_Unfreeze(); Pipe_Unfreeze();
if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_InReceived)) != HOST_SENDCONTROL_Successful) if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_InReceived)) != HOST_SENDCONTROL_Successful)

View File

@ -130,7 +130,7 @@ uint8_t Pipe_Discard_Stream(uint16_t Length
{ {
uint8_t ErrorCode; uint8_t ErrorCode;
Pipe_SetToken(PIPE_TOKEN_IN); Pipe_SetPipeToken(PIPE_TOKEN_IN);
if ((ErrorCode = Pipe_WaitUntilReady())) if ((ErrorCode = Pipe_WaitUntilReady()))
return ErrorCode; return ErrorCode;

View File

@ -432,7 +432,7 @@
#define Pipe_GetPipeToken() (UPCFG0X & PIPE_TOKEN_MASK) #define Pipe_GetPipeToken() (UPCFG0X & PIPE_TOKEN_MASK)
#define Pipe_SetToken(token) MACROS{ UPCFG0X = ((UPCFG0X & ~PIPE_TOKEN_MASK) | (token)); }MACROE #define Pipe_SetPipeToken(token) MACROS{ UPCFG0X = ((UPCFG0X & ~PIPE_TOKEN_MASK) | (token)); }MACROE
#define Pipe_SetInfiniteINRequests() MACROS{ UPCONX |= (1 << INMODE); }MACROE #define Pipe_SetInfiniteINRequests() MACROS{ UPCONX |= (1 << INMODE); }MACROE

View File

@ -3,7 +3,7 @@ uint8_t TEMPLATE_FUNC_NAME (TEMPLATE_BUFFER_TYPE Buffer, uint16_t Length __CALLB
uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length)); uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length));
uint8_t ErrorCode; uint8_t ErrorCode;
Pipe_SetToken(TEMPLATE_TOKEN); Pipe_SetPipeToken(TEMPLATE_TOKEN);
if ((ErrorCode = Pipe_WaitUntilReady())) if ((ErrorCode = Pipe_WaitUntilReady()))
return ErrorCode; return ErrorCode;

View File

@ -12,6 +12,7 @@
* - Added activity LED indicators to the AVRISP project to indicate when the device is busy processing a command * - Added activity LED indicators to the AVRISP project to indicate when the device is busy processing a command
* - The USB target family and allowable USB mode tokens are now public and documented (USB_CAN_BE_*, USB_SERIES_*_AVR) * - The USB target family and allowable USB mode tokens are now public and documented (USB_CAN_BE_*, USB_SERIES_*_AVR)
* - Added new XPLAIN serial Bridge project (thanks to John Steggall) * - Added new XPLAIN serial Bridge project (thanks to John Steggall)
* - Added new RNDISHost Host LowLevel demo
* *
* <b>Changed:</b> * <b>Changed:</b>
* - Removed code in the Keyboard demos to send zeroed reports between two reports with differing numbers of keycodes * - Removed code in the Keyboard demos to send zeroed reports between two reports with differing numbers of keycodes
@ -29,6 +30,8 @@
* - Fixed broken USB_GetNextDescriptor() function causing the descriptor to jump ahead double the expected amount * - Fixed broken USB_GetNextDescriptor() function causing the descriptor to jump ahead double the expected amount
* - Fixed Pipe_IsEndpointBound() not masking the given Endpoint Address against PIPE_EPNUM_MASK * - Fixed Pipe_IsEndpointBound() not masking the given Endpoint Address against PIPE_EPNUM_MASK
* - Fixed host state machine not enabling Auto VBUS mode when HOST_DEVICE_SETTLE_DELAY_MS is set to zero * - Fixed host state machine not enabling Auto VBUS mode when HOST_DEVICE_SETTLE_DELAY_MS is set to zero
* - Fixed misnamed Pipe_SetPipeToken() macro for setting a pipe's direction
* - Fixed CDCHost failing on devices with bidirectional endpoints
* *
* \section Sec_ChangeLog091122 Version 091122 * \section Sec_ChangeLog091122 Version 091122
* *

View File

@ -86,6 +86,7 @@
* USB HID class * USB HID class
* - <b>PrinterHost</b> - Printer host demo, using the low level LUFA APIs to implement the USB Printer class * - <b>PrinterHost</b> - Printer host demo, using the low level LUFA APIs to implement the USB Printer class
* - <b>StillImageHost</b> - Still Image Camera host demo, using the low level LUFA APIs to implement the USB Still Image class * - <b>StillImageHost</b> - Still Image Camera host demo, using the low level LUFA APIs to implement the USB Still Image class
* - <b>RNDISHost</b> - RNDIS Ethernet host demo, using the low level LUFA APIs to implement the RNDIS class
* - <b>Incomplete</b> * - <b>Incomplete</b>
* - <b>BluetoothHost</b> - Incomplete Bluetooth host demo, using the low level LUFA APIs to implement the USB Bluetooth class * - <b>BluetoothHost</b> - Incomplete Bluetooth host demo, using the low level LUFA APIs to implement the USB Bluetooth class
* - <b>DualRole</b> * - <b>DualRole</b>

View File

@ -117,13 +117,17 @@ void SetupHardware(void)
/* Hardware Initialization */ /* Hardware Initialization */
SoftUART_Init(); SoftUART_Init();
LEDs_Init();
USB_Init(); USB_Init();
} }
/** Event handler for the library USB Configuration Changed event. */ /** Event handler for the library USB Configuration Changed event. */
void EVENT_USB_Device_ConfigurationChanged(void) void EVENT_USB_Device_ConfigurationChanged(void)
{ {
CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface); LEDs_SetAllLEDs(LEDS_LED1);
if (!(CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface)))
LEDs_SetAllLEDs(LEDS_NO_LEDS);
} }
/** Event handler for the library USB Unhandled Control Request event. */ /** Event handler for the library USB Unhandled Control Request event. */

View File

@ -47,6 +47,7 @@
#include "Lib/SoftUART.h" #include "Lib/SoftUART.h"
#include <LUFA/Version.h> #include <LUFA/Version.h>
#include <LUFA/Drivers/Board/LEDs.h>
#include <LUFA/Drivers/USB/USB.h> #include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Drivers/USB/Class/CDC.h> #include <LUFA/Drivers/USB/Class/CDC.h>

View File

@ -66,7 +66,7 @@ MCU = at90usb1287
# Target board (see library "Board Types" documentation, USER or blank for projects not requiring # Target board (see library "Board Types" documentation, USER or blank for projects not requiring
# LUFA board drivers). If USER is selected, put custom board drivers in a directory called # LUFA board drivers). If USER is selected, put custom board drivers in a directory called
# "Board" inside the application directory. # "Board" inside the application directory.
BOARD = USER BOARD = XPLAIN
# Processor frequency. # Processor frequency.