Commit 67f390fe authored by Dean Camera's avatar Dean Camera
Browse files

Add explicit guards to all device mode tasks to ensure the device is connected...

Add explicit guards to all device mode tasks to ensure the device is connected and configured before running the task, to prevent any user tasks from locking up the main USB task if the device has not been properly configured.
parent bf50959b
......@@ -141,17 +141,17 @@ void EVENT_USB_UnhandledControlPacket(void)
void SideShow_Task(void)
{
/* Check if the USB System is connected to a Host */
if (USB_IsConnected)
/* Device must be connected and configured for the task to run */
if (!(USB_IsConnected) || !(USB_ConfigurationNumber))
return;
/* Select the SideShow data out endpoint */
Endpoint_SelectEndpoint(SIDESHOW_OUT_EPNUM);
/* Check to see if a new SideShow message has been received */
if (Endpoint_IsReadWriteAllowed())
{
/* Select the SideShow data out endpoint */
Endpoint_SelectEndpoint(SIDESHOW_OUT_EPNUM);
/* Check to see if a new SideShow message has been received */
if (Endpoint_IsReadWriteAllowed())
{
/* Process the received SideShow message */
Sideshow_ProcessCommandPacket();
}
/* Process the received SideShow message */
Sideshow_ProcessCommandPacket();
}
}
......@@ -151,6 +151,10 @@ void EVENT_USB_UnhandledControlPacket(void)
/** Task to manage the Audio interface, reading in ADC samples from the microphone, and them to the host. */
void USB_Audio_Task(void)
{
/* Device must be connected and configured for the task to run */
if (!(USB_IsConnected) || !(USB_ConfigurationNumber))
return;
/* Check to see if the streaming interface is selected, if not the host is not receiving audio */
if (!(StreamingAudioInterfaceSelected))
return;
......
......@@ -180,6 +180,10 @@ void EVENT_USB_UnhandledControlPacket(void)
*/
void USB_Audio_Task(void)
{
/* Device must be connected and configured for the task to run */
if (!(USB_IsConnected) || !(USB_ConfigurationNumber))
return;
/* Check to see if the streaming interface is selected, if not the host is not receiving audio */
if (!(StreamingAudioInterfaceSelected))
return;
......
......@@ -254,6 +254,10 @@ void CDC_Task(void)
"Joystick Pressed\r\n",
};
/* Device must be connected and configured for the task to run */
if (!(USB_IsConnected) || !(USB_ConfigurationNumber))
return;
#if 0
/* NOTE: Here you can use the notification endpoint to send back line state changes to the host, for the special RS-232
* handshake signal lines (and some error states), via the CONTROL_LINE_IN_* masks and the following code:
......
......@@ -229,6 +229,10 @@ void CDC1_Task(void)
uint8_t JoyStatus_LCL = Joystick_GetStatus();
static bool ActionSent = false;
/* Device must be connected and configured for the task to run */
if (!(USB_IsConnected) || !(USB_ConfigurationNumber))
return;
char* JoystickStrings[] =
{
"Joystick Up\r\n",
......@@ -288,6 +292,10 @@ void CDC1_Task(void)
*/
void CDC2_Task(void)
{
/* Device must be connected and configured for the task to run */
if (!(USB_IsConnected) || !(USB_ConfigurationNumber))
return;
/* Select the Serial Rx Endpoint */
Endpoint_SelectEndpoint(CDC2_RX_EPNUM);
......
......@@ -202,47 +202,47 @@ void CreateGenericHIDReport(uint8_t* DataArray)
void HID_Task(void)
{
/* Check if the USB system is connected to a host */
if (USB_IsConnected)
/* Device must be connected and configured for the task to run */
if (!(USB_IsConnected) || !(USB_ConfigurationNumber))
return;
Endpoint_SelectEndpoint(GENERIC_OUT_EPNUM);
/* Check to see if a packet has been sent from the host */
if (Endpoint_IsOUTReceived())
{
Endpoint_SelectEndpoint(GENERIC_OUT_EPNUM);
/* Check to see if a packet has been sent from the host */
if (Endpoint_IsOUTReceived())
/* Check to see if the packet contains data */
if (Endpoint_IsReadWriteAllowed())
{
/* Check to see if the packet contains data */
if (Endpoint_IsReadWriteAllowed())
{
/* Create a temporary buffer to hold the read in report from the host */
uint8_t GenericData[GENERIC_REPORT_SIZE];
/* Read Generic Report Data */
Endpoint_Read_Stream_LE(&GenericData, sizeof(GenericData));
/* Process Generic Report Data */
ProcessGenericHIDReport(GenericData);
}
/* Create a temporary buffer to hold the read in report from the host */
uint8_t GenericData[GENERIC_REPORT_SIZE];
/* Read Generic Report Data */
Endpoint_Read_Stream_LE(&GenericData, sizeof(GenericData));
/* Process Generic Report Data */
ProcessGenericHIDReport(GenericData);
}
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearOUT();
}
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearOUT();
}
Endpoint_SelectEndpoint(GENERIC_IN_EPNUM);
Endpoint_SelectEndpoint(GENERIC_IN_EPNUM);
/* Check to see if the host is ready to accept another packet */
if (Endpoint_IsINReady())
{
/* Create a temporary buffer to hold the report to send to the host */
uint8_t GenericData[GENERIC_REPORT_SIZE];
/* Check to see if the host is ready to accept another packet */
if (Endpoint_IsINReady())
{
/* Create a temporary buffer to hold the report to send to the host */
uint8_t GenericData[GENERIC_REPORT_SIZE];
/* Create Generic Report Data */
CreateGenericHIDReport(GenericData);
/* Create Generic Report Data */
CreateGenericHIDReport(GenericData);
/* Write Generic Report Data */
Endpoint_Write_Stream_LE(&GenericData, sizeof(GenericData));
/* Write Generic Report Data */
Endpoint_Write_Stream_LE(&GenericData, sizeof(GenericData));
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
}
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
}
}
......@@ -181,28 +181,28 @@ bool GetNextReport(USB_JoystickReport_Data_t* ReportData)
/** Function to manage HID report generation and transmission to the host. */
void HID_Task(void)
{
/* Check if the USB System is connected to a Host */
if (USB_IsConnected)
/* Device must be connected and configured for the task to run */
if (!(USB_IsConnected) || !(USB_ConfigurationNumber))
return;
/* Select the Joystick Report Endpoint */
Endpoint_SelectEndpoint(JOYSTICK_EPNUM);
/* Check to see if the host is ready for another packet */
if (Endpoint_IsINReady())
{
/* Select the Joystick Report Endpoint */
Endpoint_SelectEndpoint(JOYSTICK_EPNUM);
/* Check to see if the host is ready for another packet */
if (Endpoint_IsINReady())
{
USB_JoystickReport_Data_t JoystickReportData;
/* Create the next HID report to send to the host */
GetNextReport(&JoystickReportData);
USB_JoystickReport_Data_t JoystickReportData;
/* Write Joystick Report Data */
Endpoint_Write_Stream_LE(&JoystickReportData, sizeof(JoystickReportData));
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
/* Clear the report data afterwards */
memset(&JoystickReportData, 0, sizeof(JoystickReportData));
}
/* Create the next HID report to send to the host */
GetNextReport(&JoystickReportData);
/* Write Joystick Report Data */
Endpoint_Write_Stream_LE(&JoystickReportData, sizeof(JoystickReportData));
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
/* Clear the report data afterwards */
memset(&JoystickReportData, 0, sizeof(JoystickReportData));
}
}
......@@ -377,13 +377,13 @@ void ReceiveNextReport(void)
/** Function to manage HID report generation and transmission to the host, when in report mode. */
void HID_Task(void)
{
/* Check if the USB system is connected to a host */
if (USB_IsConnected)
{
/* Send the next keypress report to the host */
SendNextReport();
/* Device must be connected and configured for the task to run */
if (!(USB_IsConnected) || !(USB_ConfigurationNumber))
return;
/* Send the next keypress report to the host */
SendNextReport();
/* Process the LED report sent from the host */
ReceiveNextReport();
}
/* Process the LED report sent from the host */
ReceiveNextReport();
}
......@@ -212,6 +212,10 @@ void Keyboard_HID_Task(void)
{
uint8_t JoyStatus_LCL = Joystick_GetStatus();
/* Device must be connected and configured for the task to run */
if (!(USB_IsConnected) || !(USB_ConfigurationNumber))
return;
/* Check if board button is not pressed, if so mouse mode enabled */
if (!(Buttons_GetStatus() & BUTTONS_BUTTON1))
{
......@@ -228,51 +232,47 @@ void Keyboard_HID_Task(void)
if (JoyStatus_LCL & JOY_PRESS)
KeyboardReportData.KeyCode[0] = 0x08; // E
}
/* Check if the USB system is connected to a host and report protocol mode is enabled */
if (USB_IsConnected)
/* Select the Keyboard Report Endpoint */
Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
/* Check if Keyboard Endpoint Ready for Read/Write */
if (Endpoint_IsReadWriteAllowed())
{
/* Select the Keyboard Report Endpoint */
Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
/* Check if Keyboard Endpoint Ready for Read/Write */
if (Endpoint_IsReadWriteAllowed())
{
/* Write Keyboard Report Data */
Endpoint_Write_Stream_LE(&KeyboardReportData, sizeof(KeyboardReportData));
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
/* Clear the report data afterwards */
memset(&KeyboardReportData, 0, sizeof(KeyboardReportData));
}
/* Select the Keyboard LED Report Endpoint */
Endpoint_SelectEndpoint(KEYBOARD_OUT_EPNUM);
/* Check if Keyboard LED Endpoint Ready for Read/Write */
if (Endpoint_IsReadWriteAllowed())
{
/* Read in the LED report from the host */
uint8_t LEDStatus = Endpoint_Read_Byte();
uint8_t LEDMask = LEDS_LED2;
if (LEDStatus & 0x01) // NUM Lock
LEDMask |= LEDS_LED1;
if (LEDStatus & 0x02) // CAPS Lock
LEDMask |= LEDS_LED3;
/* Write Keyboard Report Data */
Endpoint_Write_Stream_LE(&KeyboardReportData, sizeof(KeyboardReportData));
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
/* Clear the report data afterwards */
memset(&KeyboardReportData, 0, sizeof(KeyboardReportData));
}
/* Select the Keyboard LED Report Endpoint */
Endpoint_SelectEndpoint(KEYBOARD_OUT_EPNUM);
/* Check if Keyboard LED Endpoint Ready for Read/Write */
if (Endpoint_IsReadWriteAllowed())
{
/* Read in the LED report from the host */
uint8_t LEDStatus = Endpoint_Read_Byte();
uint8_t LEDMask = LEDS_LED2;
if (LEDStatus & 0x01) // NUM Lock
LEDMask |= LEDS_LED1;
if (LEDStatus & 0x02) // CAPS Lock
LEDMask |= LEDS_LED3;
if (LEDStatus & 0x04) // SCROLL Lock
LEDMask |= LEDS_LED4;
if (LEDStatus & 0x04) // SCROLL Lock
LEDMask |= LEDS_LED4;
/* Set the status LEDs to the current Keyboard LED status */
LEDs_SetAllLEDs(LEDMask);
/* Set the status LEDs to the current Keyboard LED status */
LEDs_SetAllLEDs(LEDMask);
/* Handshake the OUT Endpoint - clear endpoint and ready for next report */
Endpoint_ClearOUT();
}
/* Handshake the OUT Endpoint - clear endpoint and ready for next report */
Endpoint_ClearOUT();
}
}
......@@ -283,6 +283,10 @@ void Mouse_HID_Task(void)
{
uint8_t JoyStatus_LCL = Joystick_GetStatus();
/* Device must be connected and configured for the task to run */
if (!(USB_IsConnected) || !(USB_ConfigurationNumber))
return;
/* Check if board button is pressed, if so mouse mode enabled */
if (Buttons_GetStatus() & BUTTONS_BUTTON1)
{
......@@ -300,23 +304,19 @@ void Mouse_HID_Task(void)
MouseReportData.Button = (1 << 0);
}
/* Check if the USB system is connected to a host and report protocol mode is enabled */
if (USB_IsConnected)
{
/* Select the Mouse Report Endpoint */
Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
/* Select the Mouse Report Endpoint */
Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
/* Check if Mouse Endpoint Ready for Read/Write */
if (Endpoint_IsReadWriteAllowed())
{
/* Write Mouse Report Data */
Endpoint_Write_Stream_LE(&MouseReportData, sizeof(MouseReportData));
/* Check if Mouse Endpoint Ready for Read/Write */
if (Endpoint_IsReadWriteAllowed())
{
/* Write Mouse Report Data */
Endpoint_Write_Stream_LE(&MouseReportData, sizeof(MouseReportData));
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
/* Clear the report data afterwards */
memset(&MouseReportData, 0, sizeof(MouseReportData));
}
/* Clear the report data afterwards */
memset(&MouseReportData, 0, sizeof(MouseReportData));
}
}
......@@ -116,16 +116,17 @@ void MIDI_Task(void)
{
static uint8_t PrevJoystickStatus;
/* Select the MIDI IN stream */
/* Device must be connected and configured for the task to run */
if (!(USB_IsConnected) || !(USB_ConfigurationNumber))
return;
Endpoint_SelectEndpoint(MIDI_STREAM_IN_EPNUM);
/* Check if endpoint is ready to be written to */
if (Endpoint_IsINReady())
{
uint8_t MIDICommand = 0;
uint8_t MIDIPitch;
/* Get current joystick mask, XOR with previous to detect joystick changes */
uint8_t JoystickStatus = Joystick_GetStatus();
uint8_t JoystickChanges = (JoystickStatus ^ PrevJoystickStatus);
......
......@@ -313,10 +313,10 @@ void SendNextReport(void)
/** Task to manage HID report generation and transmission to the host, when in report mode. */
void Mouse_Task(void)
{
/* Check if the USB system is connected to a host */
if (USB_IsConnected)
{
/* Send the next mouse report to the host */
SendNextReport();
}
/* Device must be connected and configured for the task to run */
if (!(USB_IsConnected) || !(USB_ConfigurationNumber))
return;
/* Send the next mouse report to the host */
SendNextReport();
}
......@@ -284,6 +284,10 @@ void Ethernet_Task(void)
outgoing frames should be loaded into the FrameOUT structure. Both structures can only hold a single
Ethernet frame at a time, so the FrameInBuffer bool is used to indicate when the buffers contain data. */
/* Device must be connected and configured for the task to run */
if (!(USB_IsConnected) || !(USB_ConfigurationNumber))
return;
/* Check if a frame has been written to the IN frame buffer */
if (FrameIN.FrameInBuffer)
{
......
......@@ -204,89 +204,90 @@ void EVENT_USB_UnhandledControlPacket(void)
/** Task to manage CDC data transmission and reception to and from the host, from and to the physical USART. */
void CDC_Task(void)
{
if (USB_IsConnected)
{
/* Device must be connected and configured for the task to run */
if (!(USB_IsConnected) || !(USB_ConfigurationNumber))
return;
#if 0
/* NOTE: Here you can use the notification endpoint to send back line state changes to the host, for the special RS-232
handshake signal lines (and some error states), via the CONTROL_LINE_IN_* masks and the following code:
*/
/* NOTE: Here you can use the notification endpoint to send back line state changes to the host, for the special RS-232
handshake signal lines (and some error states), via the CONTROL_LINE_IN_* masks and the following code:
*/
USB_Notification_Header_t Notification = (USB_Notification_Header_t)
{
.NotificationType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
.Notification = NOTIF_SerialState,
.wValue = 0,
.wIndex = 0,
.wLength = sizeof(uint16_t),
};
uint16_t LineStateMask;
// Set LineStateMask here to a mask of CONTROL_LINE_IN_* masks to set the input handshake line states to send to the host
USB_Notification_Header_t Notification = (USB_Notification_Header_t)
{
.NotificationType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
.Notification = NOTIF_SerialState,
.wValue = 0,
.wIndex = 0,
.wLength = sizeof(uint16_t),
};
Endpoint_SelectEndpoint(CDC_NOTIFICATION_EPNUM);
Endpoint_Write_Stream_LE(&Notification, sizeof(Notification));
Endpoint_Write_Stream_LE(&LineStateMask, sizeof(LineStateMask));
Endpoint_ClearIN();
uint16_t LineStateMask;
// Set LineStateMask here to a mask of CONTROL_LINE_IN_* masks to set the input handshake line states to send to the host
Endpoint_SelectEndpoint(CDC_NOTIFICATION_EPNUM);
Endpoint_Write_Stream_LE(&Notification, sizeof(Notification));
Endpoint_Write_Stream_LE(&LineStateMask, sizeof(LineStateMask));
Endpoint_ClearIN();
#endif
/* Select the Serial Rx Endpoint */
Endpoint_SelectEndpoint(CDC_RX_EPNUM);
/* Check to see if a packet has been received from the host */
if (Endpoint_IsOUTReceived())
/* Select the Serial Rx Endpoint */
Endpoint_SelectEndpoint(CDC_RX_EPNUM);
/* Check to see if a packet has been received from the host */
if (Endpoint_IsOUTReceived())
{
/* Read the bytes in from the endpoint into the buffer while space is available */
while (Endpoint_BytesInEndpoint() && (Rx_Buffer.Elements != BUFF_STATICSIZE))
{
/* Read the bytes in from the endpoint into the buffer while space is available */
while (Endpoint_BytesInEndpoint() && (Rx_Buffer.Elements != BUFF_STATICSIZE))
{
/* Store each character from the endpoint */
Buffer_StoreElement(&Rx_Buffer, Endpoint_Read_Byte());
}
/* Check to see if all bytes in the current packet have been read */
if (!(Endpoint_BytesInEndpoint()))
{
/* Clear the endpoint buffer */
Endpoint_ClearOUT();
}
/* Store each character from the endpoint */
Buffer_StoreElement(&Rx_Buffer, Endpoint_Read_Byte());
}
/* Check if Rx buffer contains data - if so, send it */
if (Rx_Buffer.Elements)
Serial_TxByte(Buffer_GetElement(&Rx_Buffer));
/* Check to see if all bytes in the current packet have been read */
if (!(Endpoint_BytesInEndpoint()))
{
/* Clear the endpoint buffer */
Endpoint_ClearOUT();
}
}
/* Check if Rx buffer contains data - if so, send it */
if (Rx_Buffer.Elements)
Serial_TxByte(Buffer_GetElement(&Rx_Buffer));
/* Select the Serial Tx Endpoint */
Endpoint_SelectEndpoint(CDC_TX_EPNUM);
/* Select the Serial Tx Endpoint */
Endpoint_SelectEndpoint(CDC_TX_EPNUM);
/* Check if the Tx buffer contains anything to be sent to the host */
if (Tx_Buffer.Elements)
{
/* Wait until Serial Tx Endpoint Ready for Read/Write */
while (!(Endpoint_IsReadWriteAllowed()));
/* Write the bytes from the buffer to the endpoint while space is available */
while (Tx_Buffer.Elements && Endpoint_IsReadWriteAllowed())
{
/* Write each byte retreived from the buffer to the endpoint */
Endpoint_Write_Byte(Buffer_GetElement(&Tx_Buffer));
}
/* Remember if the packet to send completely fills the endpoint */
bool IsFull = (Endpoint_BytesInEndpoint() == CDC_TXRX_EPSIZE);
/* Send the data */
Endpoint_ClearIN();
/* Check if the Tx buffer contains anything to be sent to the host */
if (Tx_Buffer.Elements)
/* If no more data to send and the last packet filled the endpoint, send an empty packet to release
* the buffer on the receiver (otherwise all data will be cached until a non-full packet is received) */
if (IsFull && !(Tx_Buffer.Elements))
{
/* Wait until Serial Tx Endpoint Ready for Read/Write */
while (!(Endpoint_IsReadWriteAllowed()));
/* Write the bytes from the buffer to the endpoint while space is available */
while (Tx_Buffer.Elements && Endpoint_IsReadWriteAllowed())
{
/* Write each byte retreived from the buffer to the endpoint */
Endpoint_Write_Byte(Buffer_GetElement(&Tx_Buffer));
}
/* Remember if the packet to send completely fills the endpoint */
bool IsFull = (Endpoint_BytesInEndpoint() == CDC_TXRX_EPSIZE);
/* Send the data */
Endpoint_ClearIN();
/* If no more data to send and the last packet filled the endpoint, send an empty packet to release
* the buffer on the receiver (otherwise all data will be cached until a non-full packet is received) */
if (IsFull && !(Tx_Buffer.Elements))
{
/* Wait until Serial Tx Endpoint Ready for Read/Write */
while (!(Endpoint_IsReadWriteAllowed()));
/* Send an empty packet to terminate the transfer */
Endpoint_ClearIN();
}
/* Send an empty packet to terminate the transfer */
Endpoint_ClearIN();
}
}
}
......
......@@ -62,7 +62,7 @@ int main(void)
{
SetupHardware();
puts_P(PSTR(ESC_FG_CYAN "CDC Host Demo running.\r\n"));