Commit 24e621a8 authored by Dean Camera's avatar Dean Camera
Browse files

Altered the CDC Deivice and Host Class drivers' receive byte routines, so that...

Altered the CDC Deivice and Host Class drivers' receive byte routines, so that no data is indicated by a negative return value.

Added auto flushing of OUT data to the CDC Host Class driver's USBTask function to automatically flush the send pipe buffer.
parent 7c8d16fd
......@@ -101,12 +101,12 @@ int main(void)
CheckJoystickMovement();
/* Discard all received data on the first CDC interface */
while (CDC_Device_BytesReceived(&VirtualSerial1_CDC_Interface))
CDC_Device_ReceiveByte(&VirtualSerial1_CDC_Interface);
CDC_Device_ReceiveByte(&VirtualSerial1_CDC_Interface);
/* Echo all received data on the second CDC interface */
while (CDC_Device_BytesReceived(&VirtualSerial2_CDC_Interface))
CDC_Device_SendByte(&VirtualSerial2_CDC_Interface, CDC_Device_ReceiveByte(&VirtualSerial2_CDC_Interface));
int16_t ReceivedByte; = CDC_Device_ReceiveByte(&VirtualSerial2_CDC_Interface);
if (!(ReceivedByte < 0))
CDC_Device_SendByte(&VirtualSerial2_CDC_Interface, (uint8_t)ReceivedByte);
CDC_Device_USBTask(&VirtualSerial1_CDC_Interface);
CDC_Device_USBTask(&VirtualSerial2_CDC_Interface);
......
......@@ -83,8 +83,7 @@ int main(void)
CheckJoystickMovement();
/* Must throw away unused bytes from the host, or it will lock up while waiting for the device */
while (CDC_Device_BytesReceived(&VirtualSerial_CDC_Interface))
CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
USB_USBTask();
......
......@@ -97,8 +97,7 @@ int main(void)
CheckJoystickMovement();
/* Must throw away unused bytes from the host, or it will lock up while waiting for the device */
while (CDC_Device_BytesReceived(&VirtualSerial_CDC_Interface))
CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
HID_Device_USBTask(&Mouse_HID_Interface);
......
......@@ -111,10 +111,9 @@ int main(void)
if (CDC_Host_BytesReceived(&VirtualSerial_CDC_Interface))
{
/* Echo received bytes from the attached device through the USART */
while (CDC_Host_BytesReceived(&VirtualSerial_CDC_Interface))
putchar(CDC_Host_ReceiveByte(&VirtualSerial_CDC_Interface));
CDC_Host_Flush(&VirtualSerial_CDC_Interface);
int16_t ReceivedByte = CDC_Host_ReceiveByte(&VirtualSerial_CDC_Interface);
if (!(ReceivedByte < 0))
putchar(ReceivedByte);
}
break;
......
......@@ -128,11 +128,6 @@ void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
{
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
return;
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber);
if (Endpoint_IsOUTReceived() && !(Endpoint_BytesInEndpoint()))
Endpoint_ClearOUT();
CDC_Device_Flush(CDCInterfaceInfo);
}
......@@ -222,19 +217,24 @@ uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterface
}
}
uint8_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
{
uint8_t ReceivedByte = -1;
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
return 0;
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber);
uint8_t DataByte = Endpoint_Read_Byte();
if (!(Endpoint_IsOUTReceived()))
return -1;
else if (Endpoint_BytesInEndpoint())
ReceivedByte = Endpoint_Read_Byte();
if (!(Endpoint_BytesInEndpoint()))
Endpoint_ClearOUT();
return DataByte;
return ReceivedByte;
}
void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
......@@ -282,24 +282,28 @@ static int CDC_Device_putchar(char c,
static int CDC_Device_getchar(FILE* Stream)
{
if (!(CDC_Device_BytesReceived((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream))))
int16_t ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
if (ReceivedByte < 0)
return _FDEV_EOF;
return CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
return ReceivedByte;
}
static int CDC_Device_getchar_Blocking(FILE* Stream)
{
while (!(CDC_Device_BytesReceived((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream))))
int16_t ReceivedByte;
while ((ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream))) < 0)
{
if (USB_DeviceState == DEVICE_STATE_Unattached)
return _FDEV_EOF;
CDC_Device_USBTask((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
USB_USBTask();
USB_USBTask();
}
return CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
return ReceivedByte;
}
#endif
......@@ -233,7 +233,10 @@
uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
const uint8_t Data) ATTR_NON_NULL_PTR_ARG(1);
/** Determines the number of bytes received by the CDC interface from the host, waiting to be read.
/** Determines the number of bytes received by the CDC interface from the host, waiting to be read. This indicates the number
* of bytes in the OUT endpoint bank only, and thus the number of calls to \ref CDC_Device_ReceiveByte() which are guaranteed to
* succeed immediately. If multiple bytes are to be received, they should be buffered by the user application, as the endpoint
* bank will not be released back to the USB controller until all bytes are read.
*
* \pre This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
* the call will fail.
......@@ -245,17 +248,18 @@
uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Reads a byte of data from the host. If no data is waiting to be read of if a USB host is not connected, the function
* returns 0. The \ref CDC_Device_BytesReceived() function should be queried before data is received to ensure that no data
* underflow occurs.
* returns a negative value. The \ref CDC_Device_BytesReceived() function may be queried in advance to determine how many
* bytes are currently buffered in the CDC interface's data receive endpoint bank, and thus how many repeated calls to this
* function which are guaranteed to succeed.
*
* \pre This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
* the call will fail.
*
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state.
*
* \return Next received byte from the host, or 0 if no data received.
* \return Next received byte from the host, or a negative value if no data received.
*/
uint8_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Flushes any data waiting to be sent, ensuring that the send buffer is cleared.
*
......
......@@ -220,14 +220,19 @@ void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost),
NO_STREAM_CALLBACK);
}
Pipe_ClearIN();
Pipe_ClearIN();
EVENT_CDC_Host_ControLineStateChanged(CDCInterfaceInfo);
EVENT_CDC_Host_ControLineStateChanged(CDCInterfaceInfo);
}
else
{
Pipe_ClearIN();
}
}
Pipe_Freeze();
CDC_Host_Flush(CDCInterfaceInfo);
}
uint8_t CDC_Host_SetLineEncoding(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
......@@ -353,9 +358,9 @@ uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo
}
}
uint8_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
int16_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
{
uint8_t ReceivedByte = 0;
uint8_t ReceivedByte = -1;
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
return 0;
......@@ -364,11 +369,14 @@ uint8_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
Pipe_SetPipeToken(PIPE_TOKEN_IN);
Pipe_Unfreeze();
ReceivedByte = Pipe_Read_Byte();
if (!(Pipe_IsINReceived()))
return -1;
else if (Pipe_BytesInPipe())
ReceivedByte = Pipe_Read_Byte();
if (!(Pipe_BytesInPipe()))
Pipe_ClearIN();
Pipe_Freeze();
return ReceivedByte;
......@@ -426,15 +434,19 @@ static int CDC_Host_putchar(char c,
static int CDC_Host_getchar(FILE* Stream)
{
if (!(CDC_Host_BytesReceived((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream))))
int16_t ReceivedByte = CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream));
if (ReceivedByte < 0)
return _FDEV_EOF;
return CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream));
return ReceivedByte;
}
static int CDC_Host_getchar_Blocking(FILE* Stream)
{
while (!(CDC_Host_BytesReceived((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream))))
int16_t ReceivedByte;
while ((ReceivedByte = CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream))) < 0)
{
if (USB_HostState == HOST_STATE_Unattached)
return _FDEV_EOF;
......@@ -443,7 +455,7 @@ static int CDC_Host_getchar_Blocking(FILE* Stream)
USB_USBTask();
}
return CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream));
return ReceivedByte;
}
void CDC_Host_Event_Stub(void)
......
......@@ -236,7 +236,10 @@
uint8_t CDC_Host_SendByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
const uint8_t Data) ATTR_NON_NULL_PTR_ARG(1);
/** Determines the number of bytes received by the CDC interface from the device, waiting to be read.
/** Determines the number of bytes received by the CDC interface from the device, waiting to be read. This indicates the number
* of bytes in the IN pipe bank only, and thus the number of calls to \ref CDC_Host_ReceiveByte() which are guaranteed to succeed
* immediately. If multiple bytes are to be received, they should be buffered by the user application, as the pipe bank will not be
* released back to the USB controller until all bytes are read.
*
* \pre This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
* call will fail.
......@@ -248,17 +251,17 @@
uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Reads a byte of data from the device. If no data is waiting to be read of if a USB device is not connected, the function
* returns 0. The \ref CDC_Host_BytesReceived() function should be queried before data is received to ensure that no data
* underflow occurs.
* returns a negative value. The \ref CDC_Host_BytesReceived() function may be queried in advance to determine how many bytes
* are currently buffered in the CDC interface's data receive pipe.
*
* \pre This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
*
* \return Next received byte from the device, or 0 if no data received.
* \return Next received byte from the device, or a negative value if no data received.
*/
uint8_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
int16_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Flushes any data waiting to be sent, ensuring that the send buffer is cleared.
*
......
......@@ -41,6 +41,8 @@
* - Internal USB driver source files renamed and moved to ease future possible architecture ports
* - All internal pseudo-function macros have been converted to true inline functions for type-safety and readability
* - Changed LED indicator masks for the AVRISP-MKII project, so that there are defined roles for each LED
* - Altered the CDC Deivice and Host Class drivers' receive byte routines, so that no data is indicated by a negative return value
* - Added auto flushing of OUT data to the CDC Host Class driver's USBTask function to automatically flush the send pipe buffer
*
* <b>Fixed:</b>
* - Fixed AVRISP project sending a LOAD EXTENDED ADDRESS command to 128KB AVRs after programming or reading from
......
......@@ -32,6 +32,16 @@
* enhanced \ref USB_Device_SendRemoteWakeup() function. Existing code may now discard any checks to USB_Device_IsRemoteWakeupSent().
* - The USB_Device_IsUSBSuspended() macro has been removed, as it is obsolete. Existing code should compare \ref USB_DeviceState
* to see if it the device is in the \ref DEVICE_STATE_Suspended state instead.
* - The \ref CDC_Device_ReceiveByte() function has changed, and now returns a signed 16-bit integer, with -1 indicating no data was
* received. This allows for more efficient coding, as a call to \ref CDC_Device_BytesReceived() is no longer needed if the exact
* number of queued bytes received is not needed.
*
* <b>Host Mode</b>
* - The \ref CDC_Host_ReceiveByte() function has changed, and now returns a signed 16-bit integer, with -1 indicating no data was
* received. This allows for more efficient coding, as a call to \ref CDC_Device_BytesReceived() is no longer needed if the exact
* number of queued bytes received is not needed.
* - The \ref CDC_Host_USBTask() now calls \ref CDC_Host_Flush() automatically, flushing any queued data to the attached device. Manual
* flushing of the interface is no longer needed if the flushes should be in sync with calls to \ref CDC_Host_USBTask().
*
* \section Sec_Migration100513 Migrating from 100219 to 100513
*
......
......@@ -92,9 +92,10 @@ int main(void)
for (;;)
{
/* Echo bytes from the host to the target via the hardware USART */
if (CDC_Device_BytesReceived(&VirtualSerial_CDC_Interface) && (UCSR1A & (1 << UDRE1)))
int16_t ReceivedByte = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
if (!(ReceivedByte < 0) && (UCSR1A & (1 << UDRE1)))
{
UDR1 = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
UDR1 = ReceivedByte;
LEDs_TurnOnLEDs(LEDMASK_TX);
PulseMSRemaining.TxLEDPulse = TX_RX_LED_PULSE_MS;
......
......@@ -82,13 +82,9 @@ int main(void)
for (;;)
{
/* Read bytes from the USB OUT endpoint into the USART transmit buffer */
for (uint8_t DataBytesRem = CDC_Device_BytesReceived(&VirtualSerial_CDC_Interface); DataBytesRem != 0; DataBytesRem--)
{
if (RingBuffer_IsFull(&USBtoUSART_Buffer))
break;
RingBuffer_AtomicInsert(&USBtoUSART_Buffer, CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface));
}
int16_t ReceivedByte = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
if (!(ReceivedByte < 0) && !(RingBuffer_IsFull(&USBtoUSART_Buffer)))
RingBuffer_AtomicInsert(&USBtoUSART_Buffer, (uint8_t)ReceivedByte);
/* Check if the software USART flush timer has expired */
if (TIFR0 & (1 << TOV0))
......
......@@ -120,7 +120,8 @@ void UARTBridge_Task(void)
return;
/* Read bytes from the USB OUT endpoint into the UART transmit buffer */
if (CDC_Device_BytesReceived(&VirtualSerial_CDC_Interface) && !(RingBuffer_IsFull(&USBtoUART_Buffer)))
int16_t ReceivedByte = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
if (!(ReceivedByte < 0) && !(RingBuffer_IsFull(&USBtoUART_Buffer)))
RingBuffer_AtomicInsert(&USBtoUART_Buffer, CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface));
/* Check if the software UART flush timer has expired */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment