Added new Endpoint_ClearStatusStage() convenience function to assist with the status stages of control transfers.
Removed vague USB_IsConnected global - test USB_DeviceState or USB_HostState explicitly to gain previous functionality.
Removed USB_IsSuspended global - test USB_DeviceState against DEVICE_STATE_Suspended instead.
Fixed possible enumeration errors from spinloops which may fail to exit if the USB connection is severed before the exit condition becomes true.
\r
Endpoint_ClearIN();\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsOUTReceived()));\r
- Endpoint_ClearOUT();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
{\r
Endpoint_ClearSETUP();\r
\r
- while (!(Endpoint_IsOUTReceived()));\r
-\r
+ while (!(Endpoint_IsOUTReceived()))\r
+ { \r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
+ \r
for (uint8_t i = 0; i < sizeof(LineCoding); i++)\r
*(LineCodingData++) = Endpoint_Read_Byte();\r
\r
Endpoint_ClearOUT();\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
{\r
Endpoint_ClearSETUP();\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
while (!(Endpoint_IsReadWriteAllowed()))\r
{\r
Endpoint_ClearOUT();\r
- while (!(Endpoint_IsOUTReceived()));\r
+\r
+ while (!(Endpoint_IsOUTReceived()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return 0;\r
+ }\r
}\r
\r
/* Fetch the next byte from the OUT endpoint */\r
if (!(Endpoint_IsReadWriteAllowed()))\r
{\r
Endpoint_ClearIN();\r
- while (!(Endpoint_IsINReady()));\r
+ \r
+ while (!(Endpoint_IsINReady()))\r
+ { \r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
}\r
\r
/* Write the next byte to the OUT endpoint */\r
/* If a full endpoint's worth of data was sent, we need to send an empty packet afterwards to signal end of transfer */\r
if (IsEndpointFull)\r
{\r
- while (!(Endpoint_IsINReady()));\r
+ while (!(Endpoint_IsINReady()))\r
+ { \r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
+\r
Endpoint_ClearIN();\r
}\r
\r
/* Wait until the data has been sent to the host */\r
- while (!(Endpoint_IsINReady()));\r
+ while (!(Endpoint_IsINReady()))\r
+ { \r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
\r
/* Select the OUT endpoint */\r
Endpoint_SelectEndpoint(CDC_RX_EPNUM);\r
/* If the request has a data stage, load it into the command struct */\r
if (SentCommand.DataSize)\r
{\r
- while (!(Endpoint_IsOUTReceived()));\r
+ while (!(Endpoint_IsOUTReceived()))\r
+ { \r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
\r
/* First byte of the data stage is the DNLOAD request's command */\r
SentCommand.Command = Endpoint_Read_Byte();\r
if (!(Endpoint_BytesInEndpoint()))\r
{\r
Endpoint_ClearOUT();\r
- while (!(Endpoint_IsOUTReceived()));\r
+\r
+ while (!(Endpoint_IsOUTReceived()))\r
+ { \r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
}\r
\r
/* Write the next word into the current flash page */\r
if (!(Endpoint_BytesInEndpoint()))\r
{\r
Endpoint_ClearOUT();\r
- while (!(Endpoint_IsOUTReceived()));\r
+\r
+ while (!(Endpoint_IsOUTReceived()))\r
+ { \r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
}\r
\r
/* Read the byte from the USB interface and write to to the EEPROM */\r
\r
Endpoint_ClearOUT();\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
- \r
+ Endpoint_ClearStatusStage();\r
+\r
break;\r
case DFU_UPLOAD:\r
Endpoint_ClearSETUP();\r
\r
- while (!(Endpoint_IsINReady()));\r
-\r
+ while (!(Endpoint_IsINReady()))\r
+ { \r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
+ \r
if (DFU_State != dfuUPLOAD_IDLE)\r
{\r
if ((DFU_State == dfuERROR) && IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01)) // Blank Check\r
if (Endpoint_BytesInEndpoint() == FIXED_CONTROL_ENDPOINT_SIZE)\r
{\r
Endpoint_ClearIN();\r
- while (!(Endpoint_IsINReady()));\r
+\r
+ while (!(Endpoint_IsINReady()))\r
+ { \r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
}\r
\r
/* Read the flash word and send it via USB to the host */\r
if (Endpoint_BytesInEndpoint() == FIXED_CONTROL_ENDPOINT_SIZE)\r
{\r
Endpoint_ClearIN();\r
- while (!(Endpoint_IsINReady()));\r
+ \r
+ while (!(Endpoint_IsINReady()))\r
+ { \r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
}\r
\r
/* Read the EEPROM byte and send it via USB to the host */\r
\r
Endpoint_ClearIN();\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsOUTReceived()));\r
- Endpoint_ClearOUT();\r
-\r
+ Endpoint_ClearStatusStage();\r
break;\r
case DFU_GETSTATUS:\r
Endpoint_ClearSETUP();\r
\r
Endpoint_ClearIN();\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsOUTReceived()));\r
- Endpoint_ClearOUT();\r
- \r
+ Endpoint_ClearStatusStage();\r
break; \r
case DFU_CLRSTATUS:\r
Endpoint_ClearSETUP();\r
/* Reset the status value variable to the default OK status */\r
DFU_Status = OK;\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
- \r
+ Endpoint_ClearStatusStage();\r
break;\r
case DFU_GETSTATE:\r
Endpoint_ClearSETUP();\r
\r
Endpoint_ClearIN();\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsOUTReceived()));\r
- Endpoint_ClearOUT();\r
-\r
+ Endpoint_ClearStatusStage();\r
break;\r
case DFU_ABORT:\r
Endpoint_ClearSETUP();\r
\r
/* Reset the current state variable to the default idle state */\r
DFU_State = dfuIDLE;\r
- \r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
\r
+ Endpoint_ClearStatusStage();\r
break;\r
}\r
}\r
Endpoint_ClearOUT();\r
\r
/* Wait until next data packet received */\r
- while (!(Endpoint_IsOUTReceived()));\r
+ while (!(Endpoint_IsOUTReceived()))\r
+ { \r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
}\r
else\r
{\r
\r
/* Wait until the command (report) has been sent by the host */\r
while (!(Endpoint_IsOUTReceived()));\r
-\r
+ \r
/* Read in the write destination address */\r
uint16_t PageAddress = Endpoint_Read_Word_LE();\r
\r
\r
Endpoint_ClearOUT();\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
Dataflash_SendAddressBytes(0, CurrDFPageByte);\r
\r
/* Wait until endpoint is ready before continuing */\r
- while (!(Endpoint_IsReadWriteAllowed()));\r
+ while (!(Endpoint_IsReadWriteAllowed()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
\r
while (TotalBlocks)\r
{\r
Endpoint_ClearOUT();\r
\r
/* Wait until the host has sent another packet */\r
- while (!(Endpoint_IsReadWriteAllowed()));\r
+ while (!(Endpoint_IsReadWriteAllowed()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
}\r
\r
/* Check if end of dataflash page reached */\r
Dataflash_SendByte(0x00);\r
\r
/* Wait until endpoint is ready before continuing */\r
- while (!(Endpoint_IsReadWriteAllowed()));\r
+ while (!(Endpoint_IsReadWriteAllowed()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
\r
while (TotalBlocks)\r
{\r
Endpoint_ClearIN();\r
\r
/* Wait until the endpoint is ready for more data */\r
- while (!(Endpoint_IsReadWriteAllowed()));\r
+ while (!(Endpoint_IsReadWriteAllowed()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
}\r
\r
/* Check if end of dataflash page reached */\r
*/\r
ISR(USART1_RX_vect, ISR_BLOCK)\r
{\r
- if (USB_IsConnected)\r
+ if (USB_DeviceState == DEVICE_STATE_Configured)\r
Buffer_StoreElement(&Tx_Buffer, UDR1);\r
}\r
\r
void SideShow_Task(void)\r
{\r
/* Device must be connected and configured for the task to run */\r
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
/* Select the SideShow data out endpoint */\r
/* Check if the host is enabling the audio interface (setting AlternateSetting to 1) */\r
StreamingAudioInterfaceSelected = ((USB_ControlRequest.wValue) != 0);\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
void USB_Audio_Task(void)\r
{\r
/* Device must be connected and configured for the task to run */\r
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
/* Check to see if the streaming interface is selected, if not the host is not receiving audio */\r
/* Check if the host is enabling the audio interface (setting AlternateSetting to 1) */\r
StreamingAudioInterfaceSelected = ((USB_ControlRequest.wValue) != 0);\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
void USB_Audio_Task(void)\r
{\r
/* Device must be connected and configured for the task to run */\r
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
/* Check to see if the streaming interface is selected, if not the host is not receiving audio */\r
*/\r
\r
static int CDC_putchar (char c, FILE *stream)\r
-{\r
- if (!(USB_IsConnected))\r
- return -1;\r
- \r
+{ \r
Endpoint_SelectEndpoint(CDC_TX_EPNUM);\r
- while (!(Endpoint_IsReadWriteAllowed()));\r
+\r
+ while (!(Endpoint_IsReadWriteAllowed()))\r
+ {\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
+ return -1;\r
+ }\r
+\r
Endpoint_Write_Byte(c);\r
Endpoint_ClearIN();\r
\r
\r
for (;;)\r
{\r
- if (!(USB_IsConnected))\r
- return -1;\r
-\r
- while (!(Endpoint_IsReadWriteAllowed()));\r
+ while (!(Endpoint_IsReadWriteAllowed()))\r
+ {\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
+ return -1;\r
+ }\r
\r
if (!(Endpoint_BytesInEndpoint()))\r
{\r
CONTROL_LINE_OUT_* masks to determine the RTS and DTR line states using the following code:\r
*/\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
char* ReportString = NULL;\r
uint8_t JoyStatus_LCL = Joystick_GetStatus();\r
static bool ActionSent = false;\r
-\r
- char* JoystickStrings[] =\r
- {\r
- "Joystick Up\r\n",\r
- "Joystick Down\r\n",\r
- "Joystick Left\r\n",\r
- "Joystick Right\r\n",\r
- "Joystick Pressed\r\n",\r
- };\r
+ char* JoystickStrings[] =\r
+ {\r
+ "Joystick Up\r\n",\r
+ "Joystick Down\r\n",\r
+ "Joystick Left\r\n",\r
+ "Joystick Right\r\n",\r
+ "Joystick Pressed\r\n",\r
+ };\r
\r
/* Device must be connected and configured for the task to run */\r
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
#if 0\r
if (IsFull)\r
{\r
/* Wait until the endpoint is ready for another packet */\r
- while (!(Endpoint_IsINReady()));\r
+ while (!(Endpoint_IsINReady()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
\r
/* Send an empty packet to ensure that the host does not buffer data sent to it */\r
Endpoint_ClearIN();\r
/* Acknowledge the SETUP packet, ready for data transfer */\r
Endpoint_ClearSETUP();\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
char* ReportString = NULL;\r
uint8_t JoyStatus_LCL = Joystick_GetStatus();\r
static bool ActionSent = false;\r
-\r
+ char* JoystickStrings[] =\r
+ {\r
+ "Joystick Up\r\n",\r
+ "Joystick Down\r\n",\r
+ "Joystick Left\r\n",\r
+ "Joystick Right\r\n",\r
+ "Joystick Pressed\r\n",\r
+ };\r
+ \r
/* Device must be connected and configured for the task to run */\r
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
- char* JoystickStrings[] =\r
- {\r
- "Joystick Up\r\n",\r
- "Joystick Down\r\n",\r
- "Joystick Left\r\n",\r
- "Joystick Right\r\n",\r
- "Joystick Pressed\r\n",\r
- };\r
-\r
/* Determine if a joystick action has occurred */\r
if (JoyStatus_LCL & JOY_UP)\r
ReportString = JoystickStrings[0];\r
Endpoint_ClearIN();\r
\r
/* Wait until the endpoint is ready for another packet */\r
- while (!(Endpoint_IsINReady()));\r
+ while (!(Endpoint_IsINReady()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
\r
/* Send an empty packet to ensure that the host does not buffer data sent to it */\r
Endpoint_ClearIN();\r
void CDC2_Task(void)\r
{\r
/* Device must be connected and configured for the task to run */\r
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
/* Select the Serial Rx Endpoint */\r
Endpoint_ClearIN();\r
\r
/* Wait until the endpoint is ready for the next packet */\r
- while (!(Endpoint_IsINReady()));\r
+ while (!(Endpoint_IsINReady()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
\r
/* Send an empty packet to prevent host buffering */\r
Endpoint_ClearIN();\r
Endpoint_ClearSETUP();\r
\r
/* Wait until the generic report has been sent by the host */\r
- while (!(Endpoint_IsOUTReceived()));\r
+ while (!(Endpoint_IsOUTReceived()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
\r
Endpoint_Read_Control_Stream_LE(&GenericData, sizeof(GenericData));\r
\r
Endpoint_ClearOUT();\r
\r
/* Wait until the host is ready to receive the request confirmation */\r
- while (!(Endpoint_IsINReady()));\r
+ while (!(Endpoint_IsINReady()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
\r
/* Handshake the request by sending an empty IN packet */\r
Endpoint_ClearIN();\r
void HID_Task(void)\r
{\r
/* Device must be connected and configured for the task to run */\r
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
Endpoint_SelectEndpoint(GENERIC_OUT_EPNUM);\r
void HID_Task(void)\r
{\r
/* Device must be connected and configured for the task to run */\r
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
/* Select the Joystick Report Endpoint */\r
Endpoint_ClearSETUP();\r
\r
/* Wait until the LED report has been sent by the host */\r
- while (!(Endpoint_IsOUTReceived()));\r
+ while (!(Endpoint_IsOUTReceived()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
\r
/* Read in the LED report from the host */\r
uint8_t LEDStatus = Endpoint_Read_Byte();\r
/* Clear the endpoint data */\r
Endpoint_ClearOUT();\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
/* Send the flag to the host */\r
Endpoint_ClearIN();\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsOUTReceived()));\r
- Endpoint_ClearOUT();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
/* Set or clear the flag depending on what the host indicates that the current Protocol should be */\r
UsingReportProtocol = (USB_ControlRequest.wValue != 0);\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
/* Get idle period in MSB, IdleCount must be multiplied by 4 to get number of milliseconds */\r
IdleCount = ((USB_ControlRequest.wValue & 0xFF00) >> 6);\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
/* Send the flag to the host */\r
Endpoint_ClearIN();\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsOUTReceived()));\r
- Endpoint_ClearOUT();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
void HID_Task(void)\r
{\r
/* Device must be connected and configured for the task to run */\r
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
/* Send the next keypress report to the host */\r
Endpoint_ClearSETUP();\r
\r
/* Wait until the LED report has been sent by the host */\r
- while (!(Endpoint_IsOUTReceived()));\r
+ while (!(Endpoint_IsOUTReceived()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
\r
/* Read in the LED report from the host */\r
uint8_t LEDStatus = Endpoint_Read_Byte();\r
/* Clear the endpoint data */\r
Endpoint_ClearOUT();\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
uint8_t JoyStatus_LCL = Joystick_GetStatus();\r
\r
/* Device must be connected and configured for the task to run */\r
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
/* Check if board button is not pressed, if so mouse mode enabled */\r
uint8_t JoyStatus_LCL = Joystick_GetStatus();\r
\r
/* Device must be connected and configured for the task to run */\r
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
/* Check if board button is pressed, if so mouse mode enabled */\r
static uint8_t PrevJoystickStatus;\r
\r
/* Device must be connected and configured for the task to run */\r
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
Endpoint_SelectEndpoint(MIDI_STREAM_IN_EPNUM);\r
Dataflash_SendAddressBytes(0, CurrDFPageByte);\r
\r
/* Wait until endpoint is ready before continuing */\r
- while (!(Endpoint_IsReadWriteAllowed()));\r
-\r
+ while (!(Endpoint_IsReadWriteAllowed()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
+ \r
while (TotalBlocks)\r
{\r
uint8_t BytesInBlockDiv16 = 0;\r
Endpoint_ClearOUT();\r
\r
/* Wait until the host has sent another packet */\r
- while (!(Endpoint_IsReadWriteAllowed()));\r
+ while (!(Endpoint_IsReadWriteAllowed()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
}\r
\r
/* Check if end of dataflash page reached */\r
Dataflash_SendByte(0x00);\r
\r
/* Wait until endpoint is ready before continuing */\r
- while (!(Endpoint_IsReadWriteAllowed()));\r
+ while (!(Endpoint_IsReadWriteAllowed()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
\r
while (TotalBlocks)\r
{\r
Endpoint_ClearIN();\r
\r
/* Wait until the endpoint is ready for more data */\r
- while (!(Endpoint_IsReadWriteAllowed()));\r
+ while (!(Endpoint_IsReadWriteAllowed()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
}\r
\r
/* Check if end of dataflash page reached */\r
/* Indicate that the current transfer should be aborted */\r
IsMassStoreReset = true; \r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
\r
Endpoint_ClearIN();\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsOUTReceived()));\r
- Endpoint_ClearOUT();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
*/\r
void MassStorage_Task(void)\r
{\r
- /* Check if the USB System is connected to a Host */\r
- if (USB_IsConnected)\r
+ /* Device must be connected and configured for the task to run */\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
+ return;\r
+ \r
+ /* Select the Data Out Endpoint */\r
+ Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);\r
+ \r
+ /* Check to see if a command from the host has been issued */\r
+ if (Endpoint_IsReadWriteAllowed())\r
{\r
- /* Select the Data Out Endpoint */\r
- Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);\r
- \r
- /* Check to see if a command from the host has been issued */\r
- if (Endpoint_IsReadWriteAllowed())\r
- {\r
- /* Indicate busy */\r
- LEDs_SetAllLEDs(LEDMASK_USB_BUSY);\r
+ /* Indicate busy */\r
+ LEDs_SetAllLEDs(LEDMASK_USB_BUSY);\r
\r
- /* Process sent command block from the host */\r
- if (ReadInCommandBlock())\r
- {\r
- /* Check direction of command, select Data IN endpoint if data is from the device */\r
- if (CommandBlock.Flags & COMMAND_DIRECTION_DATA_IN)\r
- Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);\r
+ /* Process sent command block from the host */\r
+ if (ReadInCommandBlock())\r
+ {\r
+ /* Check direction of command, select Data IN endpoint if data is from the device */\r
+ if (CommandBlock.Flags & COMMAND_DIRECTION_DATA_IN)\r
+ Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);\r
\r
- /* Decode the received SCSI command */\r
- SCSI_DecodeSCSICommand();\r
+ /* Decode the received SCSI command */\r
+ SCSI_DecodeSCSICommand();\r
\r
- /* Load in the CBW tag into the CSW to link them together */\r
- CommandStatus.Tag = CommandBlock.Tag;\r
+ /* Load in the CBW tag into the CSW to link them together */\r
+ CommandStatus.Tag = CommandBlock.Tag;\r
\r
- /* Load in the data residue counter into the CSW */\r
- CommandStatus.DataTransferResidue = CommandBlock.DataTransferLength;\r
+ /* Load in the data residue counter into the CSW */\r
+ CommandStatus.DataTransferResidue = CommandBlock.DataTransferLength;\r
\r
- /* Stall the selected data pipe if command failed (if data is still to be transferred) */\r
- if ((CommandStatus.Status == Command_Fail) && (CommandStatus.DataTransferResidue))\r
- Endpoint_StallTransaction();\r
+ /* Stall the selected data pipe if command failed (if data is still to be transferred) */\r
+ if ((CommandStatus.Status == Command_Fail) && (CommandStatus.DataTransferResidue))\r
+ Endpoint_StallTransaction();\r
\r
- /* Return command status block to the host */\r
- ReturnCommandStatus();\r
- \r
- /* Check if a Mass Storage Reset occurred */\r
- if (IsMassStoreReset)\r
- {\r
- /* Reset the data endpoint banks */\r
- Endpoint_ResetFIFO(MASS_STORAGE_OUT_EPNUM);\r
- Endpoint_ResetFIFO(MASS_STORAGE_IN_EPNUM);\r
- \r
- Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);\r
- Endpoint_ClearStall();\r
- Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);\r
- Endpoint_ClearStall();\r
- }\r
-\r
- /* Indicate ready */\r
- LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
- }\r
- else\r
+ /* Return command status block to the host */\r
+ ReturnCommandStatus();\r
+ \r
+ /* Check if a Mass Storage Reset occurred */\r
+ if (IsMassStoreReset)\r
{\r
- /* Indicate error reading in the command block from the host */\r
- LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
+ /* Reset the data endpoint banks */\r
+ Endpoint_ResetFIFO(MASS_STORAGE_OUT_EPNUM);\r
+ Endpoint_ResetFIFO(MASS_STORAGE_IN_EPNUM);\r
+ \r
+ Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);\r
+ Endpoint_ClearStall();\r
+ Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);\r
+ Endpoint_ClearStall();\r
}\r
- }\r
\r
- /* Clear the abort transfer flag */\r
- IsMassStoreReset = false;\r
+ /* Indicate ready */\r
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
+ }\r
+ else\r
+ {\r
+ /* Indicate error reading in the command block from the host */\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
+ }\r
}\r
+\r
+ /* Clear the abort transfer flag */\r
+ IsMassStoreReset = false;\r
}\r
\r
/** Function to read in a command block from the host, via the bulk data OUT endpoint. This function reads in the next command block\r
/* Send the flag to the host */\r
Endpoint_ClearIN();\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsOUTReceived()));\r
- Endpoint_ClearOUT();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
/* Set or clear the flag depending on what the host indicates that the current Protocol should be */\r
UsingReportProtocol = (USB_ControlRequest.wValue != 0);\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
/* Get idle period in MSB, must multiply by 4 to get the duration in milliseconds */\r
IdleCount = ((USB_ControlRequest.wValue & 0xFF00) >> 6);\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
/* Send the flag to the host */\r
Endpoint_ClearIN();\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsOUTReceived()));\r
- Endpoint_ClearOUT();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
void Mouse_Task(void)\r
{\r
/* Device must be connected and configured for the task to run */\r
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
/* Send the next mouse report to the host */\r
Ethernet frame at a time, so the FrameInBuffer bool is used to indicate when the buffers contain data. */\r
\r
/* Device must be connected and configured for the task to run */\r
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
/* Check if a frame has been written to the IN frame buffer */\r
CONTROL_LINE_OUT_* masks to determine the RTS and DTR line states using the following code:\r
*/\r
\r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
void CDC_Task(void)\r
{\r
/* Device must be connected and configured for the task to run */\r
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
#if 0\r
if (Tx_Buffer.Elements)\r
{\r
/* Wait until Serial Tx Endpoint Ready for Read/Write */\r
- while (!(Endpoint_IsReadWriteAllowed()));\r
+ while (!(Endpoint_IsReadWriteAllowed()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
\r
/* Write the bytes from the buffer to the endpoint while space is available */\r
while (Tx_Buffer.Elements && Endpoint_IsReadWriteAllowed())\r
if (IsFull && !(Tx_Buffer.Elements))\r
{\r
/* Wait until Serial Tx Endpoint Ready for Read/Write */\r
- while (!(Endpoint_IsReadWriteAllowed()));\r
-\r
+ while (!(Endpoint_IsReadWriteAllowed()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
+ \r
/* Send an empty packet to terminate the transfer */\r
Endpoint_ClearIN();\r
}\r
ISR(USART1_RX_vect, ISR_BLOCK)\r
{\r
/* Only store received characters if the USB interface is connected */\r
- if (USB_IsConnected)\r
- {\r
- /* Character received, store it into the buffer */\r
- Buffer_StoreElement(&Tx_Buffer, UDR1);\r
- }\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
+ Buffer_StoreElement(&Tx_Buffer, UDR1);\r
}\r
\r
/** Reconfigures the USART to match the current serial port settings issued by the host as closely as possible. */\r
\r
do\r
{\r
- while (!(Bluetooth_GetNextHCIEventHeader()));\r
+ while (!(Bluetooth_GetNextHCIEventHeader()))\r
+ {\r
+ if (USB_HostState == HOST_STATE_Unattached)\r
+ return;\r
+ }\r
+ \r
Bluetooth_DiscardRemainingHCIEventParameters();\r
} while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);\r
\r
\r
do\r
{\r
- while (!(Bluetooth_GetNextHCIEventHeader()));\r
+ while (!(Bluetooth_GetNextHCIEventHeader()))\r
+ {\r
+ if (USB_HostState == HOST_STATE_Unattached)\r
+ return;\r
+ }\r
+\r
Bluetooth_DiscardRemainingHCIEventParameters();\r
} while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);\r
\r
EventMask[3], EventMask[2], EventMask[1], EventMask[0]);\r
do\r
{\r
- while (!(Bluetooth_GetNextHCIEventHeader()));\r
+ while (!(Bluetooth_GetNextHCIEventHeader()))\r
+ {\r
+ if (USB_HostState == HOST_STATE_Unattached)\r
+ return;\r
+ }\r
+\r
Bluetooth_DiscardRemainingHCIEventParameters();\r
} while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);\r
\r
\r
do\r
{\r
- while (!(Bluetooth_GetNextHCIEventHeader()));\r
+ while (!(Bluetooth_GetNextHCIEventHeader()))\r
+ {\r
+ if (USB_HostState == HOST_STATE_Unattached)\r
+ return;\r
+ }\r
+\r
Bluetooth_DiscardRemainingHCIEventParameters();\r
} while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);\r
\r
\r
do\r
{\r
- while (!(Bluetooth_GetNextHCIEventHeader()));\r
+ while (!(Bluetooth_GetNextHCIEventHeader()))\r
+ {\r
+ if (USB_HostState == HOST_STATE_Unattached)\r
+ return;\r
+ }\r
+\r
Bluetooth_DiscardRemainingHCIEventParameters();\r
} while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);\r
\r
\r
do\r
{\r
- while (!(Bluetooth_GetNextHCIEventHeader()));\r
+ while (!(Bluetooth_GetNextHCIEventHeader()))\r
+ {\r
+ if (USB_HostState == HOST_STATE_Unattached)\r
+ return;\r
+ }\r
+\r
Bluetooth_DiscardRemainingHCIEventParameters();\r
} while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);\r
\r
\r
do\r
{\r
- while (!(Bluetooth_GetNextHCIEventHeader()));\r
+ while (!(Bluetooth_GetNextHCIEventHeader()))\r
+ { \r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
+\r
Bluetooth_DiscardRemainingHCIEventParameters();\r
} while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);\r
\r
\r
void Bluetooth_Stack_Task(void)\r
{\r
- if (!(USB_IsConnected) || (USB_HostState != HOST_STATE_Ready))\r
+ if (USB_HostState != HOST_STATE_Configured)\r
Bluetooth_HCIProcessingState = Bluetooth_Init;\r
\r
Bluetooth_ProcessHCICommands();\r
USB_HostState = HOST_STATE_WaitForDeviceRemoval;\r
break;\r
}\r
- \r
+\r
+ puts_P(PSTR("CDC Device Enumerated.\r\n"));\r
+\r
USB_HostState = HOST_STATE_Configured;\r
break;\r
case HOST_STATE_Configured:\r
- puts_P(PSTR("CDC Device Enumerated.\r\n"));\r
- \r
- USB_HostState = HOST_STATE_Ready;\r
- break;\r
- case HOST_STATE_Ready:\r
/* Select and the data IN pipe */\r
Pipe_SelectPipe(CDC_DATAPIPE_IN);\r
Pipe_Unfreeze();\r
break;\r
}\r
\r
+ puts_P(PSTR("HID Device Enumerated.\r\n"));\r
+\r
USB_HostState = HOST_STATE_Configured;\r
break;\r
case HOST_STATE_Configured:\r
- puts_P(PSTR("HID Device Enumerated.\r\n"));\r
- \r
- USB_HostState = HOST_STATE_Ready;\r
- break;\r
- case HOST_STATE_Ready:\r
ReadNextReport();\r
\r
break;\r
break;\r
}\r
\r
- USB_HostState = HOST_STATE_Configured;\r
- break;\r
- case HOST_STATE_Configured:\r
/* HID class request to set the keyboard protocol to the Boot Protocol */\r
USB_ControlRequest = (USB_Request_Header_t)\r
{\r
\r
puts_P(PSTR("Keyboard Enumerated.\r\n"));\r
\r
- USB_HostState = HOST_STATE_Ready;\r
+ USB_HostState = HOST_STATE_Configured;\r
break;\r
- case HOST_STATE_Ready:\r
+ case HOST_STATE_Configured:\r
/* If a report has been received, read and process it */\r
ReadNextReport();\r
\r
break;\r
}\r
\r
- USB_HostState = HOST_STATE_Configured;\r
- break;\r
- case HOST_STATE_Configured:\r
puts_P(PSTR("Processing HID Report.\r\n"));\r
\r
/* Get and process the device's first HID report descriptor */\r
\r
puts_P(PSTR("Keyboard Enumerated.\r\n"));\r
\r
- USB_HostState = HOST_STATE_Ready;\r
+ USB_HostState = HOST_STATE_Configured;\r
break;\r
- case HOST_STATE_Ready:\r
+ case HOST_STATE_Configured:\r
/* Select and unfreeze keyboard data pipe */\r
Pipe_SelectPipe(KEYBOARD_DATAPIPE); \r
Pipe_Unfreeze();\r
}\r
\r
/* Check to see if the device was disconnected, if so exit function */\r
- if (!(USB_IsConnected))\r
+ if (USB_HostState == HOST_STATE_Unattached)\r
return PIPE_RWSTREAM_DeviceDisconnected;\r
};\r
\r
/* Acknowledge the packet */\r
Pipe_ClearOUT();\r
\r
- while (!(Pipe_IsOUTReady()));\r
+ while (!(Pipe_IsOUTReady()))\r
+ {\r
+ if (USB_HostState == HOST_STATE_Unattached)\r
+ return PIPE_RWSTREAM_DeviceDisconnected;\r
+ }\r
}\r
\r
/* Freeze used pipe after use */\r
break;\r
}\r
\r
+ puts_P(PSTR("Mass Storage Disk Enumerated.\r\n"));\r
+\r
USB_HostState = HOST_STATE_Configured;\r
break;\r
case HOST_STATE_Configured:\r
- puts_P(PSTR("Mass Storage Disk Enumerated.\r\n"));\r
- \r
- USB_HostState = HOST_STATE_Ready;\r
- break;\r
- case HOST_STATE_Ready:\r
/* Indicate device busy via the status LEDs */\r
LEDs_SetAllLEDs(LEDMASK_USB_BUSY);\r
\r
{\r
Serial_TxByte('.');\r
\r
- if ((ErrorCode = MassStore_TestUnitReady(0)) != 0)\r
+ /* Abort if device removed */\r
+ if (USB_HostState == HOST_STATE_Unattached)\r
+ break;\r
+\r
+ if ((ErrorCode = MassStore_TestUnitReady(0)) != PIPE_RWSTREAM_NoError)\r
{\r
ShowDiskReadError(PSTR("Test Unit Ready"), false, ErrorCode);\r
\r
break;\r
}\r
}\r
- while ((SCSICommandStatus.Status != Command_Pass) && USB_IsConnected);\r
- \r
- /* Abort if device removed */\r
- if (!(USB_IsConnected))\r
- break;\r
+ while (SCSICommandStatus.Status != Command_Pass);\r
\r
puts_P(PSTR("\r\nRetrieving Capacity... "));\r
\r
while (!(Buttons_GetStatus() & BUTTONS_BUTTON1))\r
{\r
/* Abort if device removed */\r
- if (!(USB_IsConnected))\r
+ if (USB_HostState == HOST_STATE_Unattached)\r
break;\r
}\r
\r
}\r
\r
/* Abort if device removed */\r
- if (!(USB_IsConnected))\r
+ if (USB_HostState == HOST_STATE_Unattached)\r
break;\r
}\r
\r
break;\r
}\r
\r
- USB_HostState = HOST_STATE_Configured;\r
- break;\r
- case HOST_STATE_Configured:\r
/* HID class request to set the mouse protocol to the Boot Protocol */\r
USB_ControlRequest = (USB_Request_Header_t)\r
{\r
}\r
\r
puts_P(PSTR("Mouse Enumerated.\r\n"));\r
- \r
- USB_HostState = HOST_STATE_Ready;\r
+\r
+ USB_HostState = HOST_STATE_Configured;\r
break;\r
- case HOST_STATE_Ready:\r
+ case HOST_STATE_Configured:\r
/* If a report has been received, read and process it */\r
ReadNextReport();\r
\r
break;\r
}\r
\r
- USB_HostState = HOST_STATE_Configured;\r
- break;\r
- case HOST_STATE_Configured:\r
puts_P(PSTR("Processing HID Report.\r\n"));\r
\r
/* Get and process the device's first HID report descriptor */\r
}\r
\r
puts_P(PSTR("Mouse Enumerated.\r\n"));\r
- \r
- USB_HostState = HOST_STATE_Ready;\r
+\r
+ USB_HostState = HOST_STATE_Configured;\r
break;\r
- case HOST_STATE_Ready:\r
+ case HOST_STATE_Configured:\r
/* Select and unfreeze mouse data pipe */\r
Pipe_SelectPipe(MOUSE_DATAPIPE); \r
Pipe_Unfreeze();\r
return ErrorCode;\r
\r
Pipe_ClearOUT();\r
- while (!(Pipe_IsOUTReady()));\r
+ while (!(Pipe_IsOUTReady()))\r
+ {\r
+ if (USB_HostState == HOST_STATE_Unattached)\r
+ return PIPE_RWSTREAM_DeviceDisconnected;\r
+ }\r
\r
Pipe_Freeze();\r
\r
}\r
}\r
\r
- USB_HostState = HOST_STATE_Configured;\r
- break;\r
- case HOST_STATE_Configured:\r
puts_P(PSTR("Retrieving Device ID...\r\n"));\r
\r
char DeviceIDString[256];\r
printf_P(PSTR("Printer Device ID: %s\r\n"), DeviceIDString);\r
\r
puts_P(PSTR("Printer Enumerated.\r\n"));\r
- \r
- USB_HostState = HOST_STATE_Ready;\r
+\r
+ USB_HostState = HOST_STATE_Configured;\r
break;\r
- case HOST_STATE_Ready:\r
+ case HOST_STATE_Configured:\r
/* Indicate device busy via the status LEDs */\r
LEDs_SetAllLEDs(LEDMASK_USB_BUSY);\r
\r
}\r
\r
/* Check to see if the device was disconnected, if so exit function */\r
- if (!(USB_IsConnected))\r
- {\r
- /* Return error code */\r
- return PIPE_RWSTREAM_DeviceDisconnected;\r
- }\r
- };\r
+ if (USB_HostState == HOST_STATE_Unattached)\r
+ return PIPE_RWSTREAM_DeviceDisconnected;\r
+ }\r
\r
/* Freeze OUT pipe after use */\r
Pipe_SelectPipe(SIMAGE_DATA_OUT_PIPE);\r
break;\r
}\r
\r
+ puts_P(PSTR("Still Image Device Enumerated.\r\n"));\r
+\r
USB_HostState = HOST_STATE_Configured;\r
break;\r
case HOST_STATE_Configured:\r
- puts_P(PSTR("Still Image Device Enumerated.\r\n"));\r
- \r
- USB_HostState = HOST_STATE_Ready;\r
- break;\r
- case HOST_STATE_Ready:\r
/* Indicate device busy via the status LEDs */\r
LEDs_SetAllLEDs(LEDMASK_USB_BUSY);\r
\r
/* Indicate device no longer busy */\r
LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
\r
- /* Wait until USB device disconnected */\r
- while (USB_IsConnected);\r
- \r
+ USB_HostState = HOST_STATE_WaitForDeviceRemoval;\r
break;\r
}\r
}\r
\r
AudioInterfaceInfo->State.InterfaceEnabled = (USB_ControlRequest.wValue != 0);\r
\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
\r
EVENT_CDC_Device_ControLineStateChanged(CDCInterfaceInfo);\r
\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
\r
void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo)\r
{\r
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);\r
if (!(Endpoint_IsReadWriteAllowed()))\r
{\r
Endpoint_ClearIN();\r
- while (!(Endpoint_IsReadWriteAllowed()));\r
+\r
+ while (!(Endpoint_IsReadWriteAllowed()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
} \r
\r
Endpoint_ClearIN();\r
\r
void CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, char* const Data, const uint16_t Length)\r
{\r
- if (!(USB_IsConnected))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);\r
\r
void CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, const uint8_t Data)\r
{\r
- if (!(USB_IsConnected))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);\r
if (!(Endpoint_IsReadWriteAllowed()))\r
{\r
Endpoint_ClearIN();\r
- while (!(Endpoint_IsReadWriteAllowed()));\r
+ \r
+ while (!(Endpoint_IsReadWriteAllowed()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return; \r
+ }\r
}\r
\r
Endpoint_Write_Byte(Data); \r
\r
uint8_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo)\r
{\r
- if (!(USB_IsConnected))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return 0;\r
\r
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber);\r
\r
void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)\r
{\r
- if (!(USB_IsConnected))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.NotificationEndpointNumber);\r
Endpoint_Write_Byte(HIDInterfaceInfo->State.UsingReportProtocol);\r
Endpoint_ClearIN();\r
\r
- while (!(Endpoint_IsOUTReceived()));\r
- Endpoint_ClearOUT();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
\r
HIDInterfaceInfo->State.UsingReportProtocol = (USB_ControlRequest.wValue != 0x0000);\r
\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
\r
HIDInterfaceInfo->State.IdleCount = ((USB_ControlRequest.wValue & 0xFF00) >> 6);\r
\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
+ Endpoint_ClearStatusStage();\r
}\r
}\r
\r
Endpoint_Write_Byte(HIDInterfaceInfo->State.IdleCount >> 2);\r
Endpoint_ClearIN();\r
\r
- while (!(Endpoint_IsOUTReceived()));\r
- Endpoint_ClearOUT();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
\r
void HID_Device_USBTask(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo)\r
{\r
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
Endpoint_SelectEndpoint(HIDInterfaceInfo->Config.ReportINEndpointNumber);\r
\r
void MIDI_Device_SendEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, MIDI_EventPacket_t* const Event)\r
{\r
- if (!(USB_IsConnected))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpointNumber);\r
\r
bool MIDI_Device_ReceiveEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, MIDI_EventPacket_t* const Event)\r
{\r
- if (!(USB_IsConnected))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return false;\r
\r
Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataOUTEndpointNumber);\r
\r
MSInterfaceInfo->State.IsMassStoreReset = true; \r
\r
- while (!(Endpoint_IsINReady()));\r
- Endpoint_ClearIN();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
{\r
Endpoint_ClearSETUP();\r
\r
- Endpoint_Write_Byte(MSInterfaceInfo->Config.TotalLUNs - 1);\r
- \r
+ Endpoint_Write_Byte(MSInterfaceInfo->Config.TotalLUNs - 1); \r
Endpoint_ClearIN();\r
\r
- while (!(Endpoint_IsOUTReceived()));\r
- Endpoint_ClearOUT();\r
+ Endpoint_ClearStatusStage();\r
}\r
\r
break;\r
\r
void MS_Device_USBTask(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)\r
{\r
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);\r
\r
void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)\r
{\r
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))\r
+ if (USB_DeviceState != DEVICE_STATE_Configured)\r
return;\r
\r
RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;\r
* which is not always accurate (host may suspend the bus while still connected). If the actual connection state\r
* needs to be determined, VBUS should be routed to an external pin, and the auto-detect behaviour turned off by\r
* passing the NO_LIMITED_CONTROLLER_CONNECT token to the compiler via the -D switch at compile time. The connection\r
- * and disconnection events may be manually fired, and the \ref USB_IsConnected global changed manually.\r
+ * and disconnection events may be manually fired, and the \ref USB_DeviceState global changed manually.\r
*\r
* \see USBTask.h for more information on the USB management task and reducing CPU usage.\r
*/\r
* which is not always accurate (host may suspend the bus while still connected). If the actual connection state\r
* needs to be determined, VBUS should be routed to an external pin, and the auto-detect behaviour turned off by\r
* passing the NO_LIMITED_CONTROLLER_CONNECT token to the compiler via the -D switch at compile time. The connection\r
- * and disconnection events may be manually fired, and the \ref USB_IsConnected global changed manually.\r
+ * and disconnection events may be manually fired, and the \ref USB_DeviceState global changed manually.\r
*\r
* \see USBTask.h for more information on the USB management task and reducing CPU usage.\r
*/\r
{\r
EVENT_USB_VBUSConnect();\r
\r
- if (USB_IsConnected)\r
+ if (USB_DeviceState != DEVICE_STATE_Unattached)\r
EVENT_USB_Disconnect();\r
\r
USB_ResetInterface();\r
- \r
- USB_IsConnected = true;\r
\r
+ USB_DeviceState = DEVICE_STATE_Powered;\r
EVENT_USB_Connect();\r
}\r
else\r
{\r
- USB_IsConnected = false;\r
-\r
+ USB_DeviceState = DEVICE_STATE_Unattached;\r
EVENT_USB_Disconnect();\r
\r
USB_Detach();\r
if (!(USB_Options & USB_OPT_MANUAL_PLL))\r
USB_PLL_Off();\r
\r
- USB_IsSuspended = true;\r
-\r
- EVENT_USB_Suspend();\r
-\r
#if defined(USB_SERIES_2_AVR) && !defined(NO_LIMITED_CONTROLLER_CONNECT)\r
- if (USB_IsConnected)\r
- {\r
- USB_IsConnected = false;\r
- EVENT_USB_Disconnect();\r
- }\r
+ USB_DeviceState = DEVICE_STATE_Unattached;\r
+ EVENT_USB_Disconnect();\r
+ #else\r
+ USB_DeviceState = DEVICE_STATE_Suspended;\r
+ EVENT_USB_Suspend();\r
#endif\r
}\r
\r
USB_INT_Enable(USB_INT_SUSPEND);\r
\r
#if defined(USB_SERIES_2_AVR) && !defined(NO_LIMITED_CONTROLLER_CONNECT)\r
- if (!(USB_IsConnected))\r
- {\r
- USB_IsConnected = true;\r
- EVENT_USB_Connect();\r
- }\r
+ USB_DeviceState = DEVICE_STATE_Powered;\r
+ EVENT_USB_Connect();\r
+ #else\r
+ USB_DeviceState = DEVICE_STATE_Configured;\r
+ EVENT_USB_WakeUp(); \r
#endif\r
-\r
- USB_IsSuspended = false;\r
-\r
- EVENT_USB_WakeUp();\r
}\r
\r
if (USB_INT_HasOccurred(USB_INT_EORSTI) && USB_INT_IsEnabled(USB_INT_EORSTI))\r
{\r
USB_INT_Clear(USB_INT_EORSTI);\r
\r
+ USB_DeviceState = DEVICE_STATE_Default;\r
USB_ConfigurationNumber = 0;\r
\r
USB_INT_Clear(USB_INT_SUSPEND);\r
\r
USB_INT_Enable(USB_INT_DDISCI);\r
\r
- USB_HostState = HOST_STATE_Attached;\r
+ USB_HostState = HOST_STATE_Powered;\r
}\r
\r
if (USB_INT_HasOccurred(USB_INT_BCERRI) && USB_INT_IsEnabled(USB_INT_BCERRI))\r
EVENT_USB_DeviceEnumerationFailed(HOST_ENUMERROR_NoDeviceDetected, 0);\r
EVENT_USB_DeviceUnattached();\r
\r
- if (USB_IsConnected)\r
+ if (USB_HostState != HOST_STATE_Unattached)\r
EVENT_USB_Disconnect();\r
\r
USB_ResetInterface();\r
{ \r
USB_INT_Clear(USB_INT_IDTI);\r
\r
- if (USB_IsConnected)\r
- {\r
- if (USB_CurrentMode == USB_MODE_HOST)\r
- EVENT_USB_DeviceUnattached();\r
+ if (USB_DeviceState != DEVICE_STATE_Unattached)\r
+ EVENT_USB_Disconnect();\r
\r
+ if (USB_HostState != HOST_STATE_Unattached)\r
+ {\r
EVENT_USB_Disconnect();\r
+ EVENT_USB_DeviceUnattached();\r
}\r
+ \r
+ EVENT_USB_Disconnect();\r
\r
EVENT_USB_UIDChange();\r
\r
#define INCLUDE_FROM_USBTASK_C\r
#include "USBTask.h"\r
\r
-volatile bool USB_IsSuspended;\r
-volatile bool USB_IsConnected;\r
volatile bool USB_IsInitialized;\r
USB_Request_Header_t USB_ControlRequest;\r
\r
volatile uint8_t USB_HostState;\r
#endif\r
\r
+#if defined(USB_CAN_BE_DEVICE)\r
+volatile uint8_t USB_DeviceState;\r
+#endif\r
+\r
void USB_USBTask(void)\r
{\r
#if defined(USB_HOST_ONLY)\r
#if defined(USB_CAN_BE_DEVICE)\r
static void USB_DeviceTask(void)\r
{\r
- if (USB_IsConnected)\r
+ if (USB_DeviceState != DEVICE_STATE_Unattached)\r
{\r
uint8_t PrevEndpoint = Endpoint_GetCurrentEndpoint();\r
\r
\r
/* Public Interface - May be used in end-application: */\r
/* Global Variables: */\r
- /** Indicates if the USB interface is currently connected to a host if in device mode, or to a\r
- * device while running in host mode.\r
- *\r
- * \note This variable should be treated as read-only in the user application, and never manually\r
- * changed in value.\r
- *\r
- * \note For the smaller USB AVRs (AT90USBXX2) with limited USB controllers, VBUS is not available to the USB controller.\r
- * this means that the current connection state is derived from the bus suspension and wake up events by default,\r
- * which is not always accurate (host may suspend the bus while still connected). If the actual connection state\r
- * needs to be determined, VBUS should be routed to an external pin, and the auto-detect behaviour turned off by\r
- * passing the NO_LIMITED_CONTROLLER_CONNECT token to the compiler via the -D switch at compile time. The connection\r
- * and disconnection events may be manually fired, and the \ref USB_IsConnected global changed manually.\r
- *\r
- * \ingroup Group_USBManagement\r
- */\r
- extern volatile bool USB_IsConnected;\r
-\r
/** Indicates if the USB interface is currently initialized but not necessarily connected to a host\r
* or device (i.e. if \ref USB_Init() has been run). If this is false, all other library globals are invalid.\r
*\r
*/\r
extern USB_Request_Header_t USB_ControlRequest;\r
\r
- #if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__)\r
- /** Indicates if the USB interface is currently suspended by the host when in device mode. When suspended,\r
- * the device should consume minimal power, and cannot communicate to the host. If Remote Wakeup is\r
- * supported by the device and \ref USB_RemoteWakeupEnabled is true, suspension can be terminated by the device\r
- * by issuing a Remote Wakeup request.\r
- *\r
- * \note This global is only present if the user application can be a USB device.\r
- *\r
- * \note This variable should be treated as read-only in the user application, and never manually\r
- * changed in value.\r
- *\r
- * \ingroup Group_Device\r
- */\r
- extern volatile bool USB_IsSuspended;\r
- #endif\r
-\r
#if defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__)\r
/** Indicates the current host state machine state. When in host mode, this indicates the state\r
- * via one of the values of the \ref USB_Host_States_t enum values in Host.h.\r
+ * via one of the values of the \ref USB_Host_States_t enum values.\r
*\r
* This value may be altered by the user application to implement the \ref HOST_STATE_Addressed,\r
- * \ref HOST_STATE_Configured, \ref HOST_STATE_Ready and \ref HOST_STATE_Suspended states which\r
- * are not implemented by the library.\r
+ * \ref HOST_STATE_Configured and \ref HOST_STATE_Suspended states which are not implemented by\r
+ * the library.\r
*\r
* \note This global is only present if the user application can be a USB host.\r
*\r
- * \see \ref USB_Host_States_t for a list of possible host states\r
+ * \see \ref USB_Host_States_t for a list of possible device states\r
*\r
* \ingroup Group_Host\r
*/\r
extern volatile uint8_t USB_HostState;\r
#endif\r
\r
+ #if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__)\r
+ /** Indicates the current device state machine state. When in device mode, this indicates the state\r
+ * via one of the values of the \ref USB_Device_States_t enum values.\r
+ *\r
+ * This value should not be altered by the user application as it is handled automatically by the\r
+ * library. The only exception to this rule is if the NO_LIMITED_CONTROLLER_CONNECT token is used\r
+ * (see \ref EVENT_USB_Connect() and \ref EVENT_USB_Disconnect() events).\r
+ *\r
+ * \note This global is only present if the user application can be a USB device.\r
+ *\r
+ * \note This variable should be treated as read-only in the user application, and never manually\r
+ * changed in value except in the circumstances outlined above.\r
+ *\r
+ * \see \ref USB_Device_States_t for a list of possible device states\r
+ *\r
+ * \ingroup Group_Device\r
+ */\r
+ extern volatile uint8_t USB_DeviceState;\r
+ #endif\r
+\r
/* Function Prototypes: */\r
/** This is the main USB management task. The USB driver requires that this task be executed\r
* continuously when the USB system is active (device attached in host mode, or attached to a host\r
\r
static void USB_Device_SetAddress(void)\r
{\r
+ uint8_t DeviceAddress = (USB_ControlRequest.wValue & 0x7F);\r
+\r
Endpoint_ClearSETUP();\r
\r
Endpoint_ClearIN();\r
\r
- while (!(Endpoint_IsINReady()));\r
+ while (!(Endpoint_IsINReady()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
+\r
+ UDADDR = ((1 << ADDEN) | DeviceAddress);\r
\r
- UDADDR = ((1 << ADDEN) | ((uint8_t)USB_ControlRequest.wValue & 0x7F));\r
+ if (DeviceAddress)\r
+ USB_DeviceState = DEVICE_STATE_Addressed;\r
\r
return;\r
}\r
\r
Endpoint_ClearIN();\r
\r
- if (!(AlreadyConfigured) && USB_ConfigurationNumber)\r
- EVENT_USB_DeviceEnumerationComplete();\r
+ if (USB_ConfigurationNumber)\r
+ {\r
+ USB_DeviceState = DEVICE_STATE_Configured;\r
+\r
+ if (!(AlreadyConfigured))\r
+ EVENT_USB_DeviceEnumerationComplete();\r
+ }\r
+ else\r
+ {\r
+ USB_DeviceState = DEVICE_STATE_Addressed;\r
+ }\r
\r
EVENT_USB_ConfigurationChanged();\r
}\r
\r
Endpoint_ClearIN();\r
\r
- while (!(Endpoint_IsOUTReceived()));\r
+ while (!(Endpoint_IsOUTReceived()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return; \r
+ }\r
+\r
Endpoint_ClearOUT();\r
}\r
\r
\r
Endpoint_ClearIN();\r
\r
- while (!(Endpoint_IsOUTReceived()));\r
+ while (!(Endpoint_IsOUTReceived()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return; \r
+ }\r
+ \r
Endpoint_ClearOUT();\r
}\r
\r
\r
#define USB_Device_IsUSBSuspended() ((UDINT & (1 << SUSPI)) ? true : false)\r
#endif\r
-\r
+ \r
+ /* Type Defines: */\r
+ enum USB_Device_States_t\r
+ {\r
+ DEVICE_STATE_Unattached = 0, /**< Internally implemented by the library. This state indicates\r
+ * that the device is not currently connected to a host.\r
+ */\r
+ DEVICE_STATE_Powered = 1, /**< Internally implemented by the library. This state indicates\r
+ * that the device is connected to a host, but enumeration has not\r
+ * yet begun.\r
+ */\r
+ DEVICE_STATE_Default = 2, /**< Internally implemented by the library. This state indicates\r
+ * that the device's USB bus has been reset by the host and it is\r
+ * now waiting for the host to begin the enumeration process.\r
+ */\r
+ DEVICE_STATE_Addressed = 3, /**< Internally implemented by the library. This state indicates\r
+ * that the device has been addressed by the USB Host, but is not\r
+ * yet configured.\r
+ */\r
+ DEVICE_STATE_Configured = 4, /**< May be implemented by the user project. This state indicates\r
+ * that the device has been enumerated by the host and is ready\r
+ * for USB communications to begin.\r
+ */\r
+ DEVICE_STATE_Suspended = 5, /**< May be implemented by the user project. This state indicates\r
+ * that the USB bus has been suspended by the host, and the device\r
+ * should power down to a minimal power level until the bus is\r
+ * resumed.\r
+ */\r
+ };\r
+ \r
/* Function Prototypes: */\r
/** Function to retrieve a given descriptor's size and memory location from the given descriptor type value,\r
* index and language ID. This function MUST be overridden in the user application (added with full, identical \r
}\r
}\r
\r
+void Endpoint_ClearStatusStage(void)\r
+{\r
+ if (USB_ControlRequest.bmRequestType & REQDIR_DEVICETOHOST)\r
+ {\r
+ while (!(Endpoint_IsOUTReceived()))\r
+ { \r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
+\r
+ Endpoint_ClearOUT();\r
+ }\r
+ else\r
+ {\r
+ while (!(Endpoint_IsINReady()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return;\r
+ }\r
+ \r
+ Endpoint_ClearIN();\r
+ }\r
+}\r
+\r
#if !defined(CONTROL_ONLY_DEVICE)\r
uint8_t Endpoint_WaitUntilReady(void)\r
{\r
return ENDPOINT_READYWAIT_NoError; \r
}\r
\r
- if (!(USB_IsConnected))\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
return ENDPOINT_READYWAIT_DeviceDisconnected;\r
else if (Endpoint_IsStalled())\r
return ENDPOINT_READYWAIT_EndpointStalled;\r
ENDPOINT_RWSTREAM_EndpointStalled = 1, /**< The endpoint was stalled during the stream\r
* transfer by the host or device.\r
*/\r
- ENDPOINT_RWSTREAM_DeviceDisconnected = 1, /**< Device was disconnected from the host during\r
+ ENDPOINT_RWSTREAM_DeviceDisconnected = 2, /**< Device was disconnected from the host during\r
* the transfer.\r
*/\r
- ENDPOINT_RWSTREAM_Timeout = 2, /**< The host failed to accept or send the next packet\r
+ ENDPOINT_RWSTREAM_Timeout = 3, /**< The host failed to accept or send the next packet\r
* within the software timeout period set by the\r
* \ref USB_STREAM_TIMEOUT_MS macro.\r
*/\r
- ENDPOINT_RWSTREAM_CallbackAborted = 3, /**< Indicates that the stream's callback function\r
+ ENDPOINT_RWSTREAM_CallbackAborted = 4, /**< Indicates that the stream's callback function\r
* aborted the transfer early.\r
*/\r
};\r
{\r
ENDPOINT_RWCSTREAM_NoError = 0, /**< Command completed successfully, no error. */\r
ENDPOINT_RWCSTREAM_HostAborted = 1, /**< The aborted the transfer prematurely. */\r
+ ENDPOINT_RWCSTREAM_DeviceDisconnected = 2, /**< Device was disconnected from the host during\r
+ * the transfer.\r
+ */\r
};\r
\r
/* Inline Functions: */\r
* \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum.\r
*/\r
uint8_t Endpoint_WaitUntilReady(void);\r
+ \r
+ /** Completes the status stage of a control transfer on a CONTROL type endpoint automatically,\r
+ * with respect to the data direction. This is a convenience function which can be used to\r
+ * simplify user control request handling.\r
+ */\r
+ void Endpoint_ClearStatusStage(void);\r
\r
/** Reads and discards the given number of bytes from the endpoint from the given buffer,\r
* discarding fully read packets from the host as needed. The last packet is not automatically\r
* in both failure and success states; the user is responsible for manually clearing the setup OUT to\r
* finalize the transfer via the \ref Endpoint_ClearOUT() macro.\r
*\r
+ * \note This function automatically clears the control transfer's status stage. Do not manually attempt\r
+ * to clear the status stage when using this routine in a control transaction.\r
+ *\r
* \note This routine should only be used on CONTROL type endpoints.\r
*\r
* \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained\r
\r
/** EEPROM buffer source version of Endpoint_Write_Control_Stream_LE.\r
*\r
+ * \note This function automatically clears the control transfer's status stage. Do not manually attempt\r
+ * to clear the status stage when using this routine in a control transaction.\r
+ *\r
* \note This routine should only be used on CONTROL type endpoints.\r
*\r
* \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained\r
\r
/** FLASH buffer source version of \ref Endpoint_Write_Control_Stream_LE.\r
*\r
+ * \note This function automatically clears the control transfer's status stage. Do not manually attempt\r
+ * to clear the status stage when using this routine in a control transaction.\r
+ *\r
* \note The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.\r
*\r
* \note This routine should only be used on CONTROL type endpoints.\r
* in both failure and success states; the user is responsible for manually clearing the setup OUT to\r
* finalize the transfer via the \ref Endpoint_ClearOUT() macro.\r
*\r
+ * \note This function automatically clears the control transfer's status stage. Do not manually attempt\r
+ * to clear the status stage when using this routine in a control transaction.\r
+ *\r
* \note This routine should only be used on CONTROL type endpoints.\r
*\r
* \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained\r
\r
/** EEPROM buffer source version of \ref Endpoint_Write_Control_Stream_BE.\r
*\r
+ * \note This function automatically clears the control transfer's status stage. Do not manually attempt\r
+ * to clear the status stage when using this routine in a control transaction.\r
+ *\r
* \note This routine should only be used on CONTROL type endpoints.\r
*\r
* \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained\r
\r
/** FLASH buffer source version of \ref Endpoint_Write_Control_Stream_BE.\r
*\r
+ * \note This function automatically clears the control transfer's status stage. Do not manually attempt\r
+ * to clear the status stage when using this routine in a control transaction.\r
+ *\r
* \note The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.\r
*\r
* \note This routine should only be used on CONTROL type endpoints.\r
* automatically sent after success or failure states; the user is responsible for manually sending the\r
* setup IN to finalize the transfer via the \ref Endpoint_ClearIN() macro.\r
*\r
+ * \note This function automatically clears the control transfer's status stage. Do not manually attempt\r
+ * to clear the status stage when using this routine in a control transaction.\r
+ *\r
* \note This routine should only be used on CONTROL type endpoints.\r
*\r
* \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained\r
\r
/** EEPROM buffer source version of \ref Endpoint_Read_Control_Stream_LE.\r
*\r
+ * \note This function automatically clears the control transfer's status stage. Do not manually attempt\r
+ * to clear the status stage when using this routine in a control transaction.\r
+ *\r
* \note This routine should only be used on CONTROL type endpoints.\r
*\r
* \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained\r
* automatically sent after success or failure states; the user is responsible for manually sending the\r
* setup IN to finalize the transfer via the \ref Endpoint_ClearIN() macro.\r
*\r
+ * \note This function automatically clears the control transfer's status stage. Do not manually attempt\r
+ * to clear the status stage when using this routine in a control transaction.\r
+ *\r
* \note This routine should only be used on CONTROL type endpoints.\r
*\r
* \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained\r
\r
/** EEPROM buffer source version of \ref Endpoint_Read_Control_Stream_BE.\r
*\r
+ * \note This function automatically clears the control transfer's status stage. Do not manually attempt\r
+ * to clear the status stage when using this routine in a control transaction.\r
+ *\r
* \note This routine should only be used on CONTROL type endpoints.\r
*\r
* \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained\r
}\r
\r
break;\r
- case HOST_STATE_Attached:\r
+ case HOST_STATE_Powered:\r
WaitMSRemaining = HOST_DEVICE_SETTLE_DELAY_MS;\r
\r
- USB_HostState = HOST_STATE_Attached_WaitForDeviceSettle;\r
+ USB_HostState = HOST_STATE_Powered_WaitForDeviceSettle;\r
break;\r
- case HOST_STATE_Attached_WaitForDeviceSettle:\r
+ case HOST_STATE_Powered_WaitForDeviceSettle:\r
#if HOST_DEVICE_SETTLE_DELAY_MS > 0\r
_delay_ms(1);\r
\r
USB_Host_VBUS_Auto_Enable();\r
USB_Host_VBUS_Auto_On();\r
\r
- USB_HostState = HOST_STATE_Attached_WaitForConnect;\r
+ USB_HostState = HOST_STATE_Powered_WaitForConnect;\r
}\r
#else\r
- USB_HostState = HOST_STATE_Attached_WaitForConnect; \r
+ USB_HostState = HOST_STATE_Powered_WaitForConnect; \r
#endif\r
\r
break;\r
- case HOST_STATE_Attached_WaitForConnect: \r
+ case HOST_STATE_Powered_WaitForConnect: \r
if (USB_INT_HasOccurred(USB_INT_DCONNI))\r
{ \r
USB_INT_Clear(USB_INT_DCONNI);\r
USB_INT_Clear(USB_INT_VBERRI);\r
USB_INT_Enable(USB_INT_VBERRI);\r
\r
- USB_IsConnected = true;\r
EVENT_USB_Connect();\r
\r
USB_Host_ResumeBus();\r
Pipe_ClearPipes();\r
\r
- HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Attached_DoReset);\r
+ HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Powered_DoReset);\r
}\r
\r
break;\r
- case HOST_STATE_Attached_DoReset:\r
+ case HOST_STATE_Powered_DoReset:\r
USB_Host_ResetDevice();\r
\r
- HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Powered);\r
+ HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Powered_ConfigPipe);\r
break;\r
- case HOST_STATE_Powered:\r
+ case HOST_STATE_Powered_ConfigPipe:\r
Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL,\r
PIPE_TOKEN_SETUP, ENDPOINT_CONTROLEP,\r
PIPE_CONTROLPIPE_DEFAULT_SIZE, PIPE_BANK_SINGLE); \r
USB_Host_VBUS_Auto_Off();\r
\r
EVENT_USB_DeviceUnattached();\r
- \r
- if (USB_IsConnected)\r
- EVENT_USB_Disconnect();\r
+ EVENT_USB_Disconnect();\r
\r
USB_ResetInterface();\r
}\r
MS--;\r
}\r
\r
- if ((USB_IsConnected == false) || (USB_CurrentMode == USB_MODE_DEVICE))\r
+ if ((USB_HostState == HOST_STATE_Unattached) || (USB_CurrentMode == USB_MODE_DEVICE))\r
{\r
ErrorCode = HOST_WAITERROR_DeviceDisconnect;\r
\r
* \r
* \note Do not manually change to this state in the user code.\r
*/\r
- HOST_STATE_Attached = 3, /**< Internally implemented by the library. This state indicates\r
+ HOST_STATE_Powered = 3, /**< Internally implemented by the library. This state indicates\r
* that a device has been attached, and the library's internals\r
* are being configured to begin the enumeration process.\r
* \r
* \note Do not manually change to this state in the user code.\r
*/\r
- HOST_STATE_Attached_WaitForDeviceSettle = 4, /**< Internally implemented by the library. This state indicates\r
+ HOST_STATE_Powered_WaitForDeviceSettle = 4, /**< Internally implemented by the library. This state indicates\r
* that the stack is waiting for the initial settling period to\r
* elapse before beginning the enumeration process.\r
* \r
* \note Do not manually change to this state in the user code.\r
*/\r
- HOST_STATE_Attached_WaitForConnect = 5, /**< Internally implemented by the library. This state indicates\r
+ HOST_STATE_Powered_WaitForConnect = 5, /**< Internally implemented by the library. This state indicates\r
* that the stack is waiting for a connection event from the USB\r
* controller to indicate a valid USB device has been attached to\r
* the bus and is ready to be enumerated.\r
* \r
* \note Do not manually change to this state in the user code.\r
*/\r
- HOST_STATE_Attached_DoReset = 6, /**< Internally implemented by the library. This state indicates\r
+ HOST_STATE_Powered_DoReset = 6, /**< Internally implemented by the library. This state indicates\r
* that a valid USB device has been attached, and that it is\r
* will now be reset to ensure it is ready for enumeration.\r
* \r
* \note Do not manually change to this state in the user code.\r
*/\r
- HOST_STATE_Powered = 7, /**< Internally implemented by the library. This state indicates\r
+ HOST_STATE_Powered_ConfigPipe = 7, /**< Internally implemented by the library. This state indicates\r
* that the attached device is currently powered and reset, and\r
* that the control pipe is now being configured by the stack.\r
* \r
* retrieval and processing of the device descriptor) should also\r
* be placed in this state.\r
*/\r
- HOST_STATE_Configured = 12, /**< May be implemented by the user project. This state should\r
- * implement any extra device configuration (such as the setting of\r
- * class-specific parameters) before normal communication is begun\r
- * in the HOST_STATE_Ready state.\r
- */\r
- HOST_STATE_Ready = 13, /**< May be implemented by the user project. This state should\r
- * contain the main communications with the attached device. From this\r
- * this state the host state machine should be changed to either\r
- * HOST_STATE_Suspended (after the bus is manually suspended using the\r
- * USB_Host_SuspendBus() macro) or HOST_STATE_WaitForDeviceRemoval as\r
- * needed.\r
+ HOST_STATE_Configured = 12, /**< May be implemented by the user project. This state should implement the\r
+ * actual work performed on the attached device and changed to the\r
+ * HOST_STATE_Suspended or HOST_STATE_WaitForDeviceRemoval states as needed.\r
*/\r
HOST_STATE_Suspended = 15, /**< May be implemented by the user project. This state should be maintained\r
- * while the bus is suspended, and changed to either the HOST_STATE_Ready\r
+ * while the bus is suspended, and changed to either the HOST_STATE_Configured\r
* (after resuming the bus with the USB_Host_ResumeBus() macro) or the\r
* HOST_STATE_WaitForDeviceRemoval states as needed.\r
*/\r
\r
void USB_ShutDown(void)\r
{\r
- if (USB_IsConnected)\r
+ #if defined(USB_CAN_BE_DEVICE)\r
+ if (USB_DeviceState != DEVICE_STATE_Unattached)\r
+ EVENT_USB_Disconnect();\r
+ #endif\r
+ \r
+ #if defined(USB_CAN_BE_HOST)\r
+ if (USB_HostState != HOST_STATE_Unattached)\r
EVENT_USB_Disconnect();\r
+ #endif\r
\r
USB_Detach();\r
\r
USB_INT_DisableAllInterrupts();\r
USB_INT_ClearAllInterrupts();\r
\r
- USB_IsConnected = false;\r
USB_IsInitialized = false;\r
\r
#if defined(USB_CAN_BE_HOST)\r
#endif\r
\r
#if defined(USB_CAN_BE_DEVICE)\r
- USB_ConfigurationNumber = 0;\r
+ USB_DeviceState = DEVICE_STATE_Unattached;\r
+ USB_ConfigurationNumber = 0;\r
+ USB_RemoteWakeupEnabled = false;\r
+ USB_CurrentlySelfPowered = false;\r
#endif\r
\r
#if defined(CAN_BE_BOTH)\r
{\r
USB_INT_DisableAllInterrupts();\r
USB_INT_ClearAllInterrupts();\r
-\r
- USB_IsConnected = false;\r
-\r
+ \r
#if defined(USB_CAN_BE_HOST)\r
- USB_HostState = HOST_STATE_Unattached;\r
+ USB_HostState = HOST_STATE_Unattached;\r
#endif\r
-\r
+ \r
#if defined(USB_CAN_BE_DEVICE)\r
+ USB_DeviceState = DEVICE_STATE_Unattached;\r
USB_ConfigurationNumber = 0;\r
- USB_IsSuspended = false;\r
USB_RemoteWakeupEnabled = false;\r
USB_CurrentlySelfPowered = false;\r
#endif\r
\r
if (Pipe_IsStalled())\r
return PIPE_READYWAIT_PipeStalled;\r
- else if (!(USB_IsConnected))\r
+ else if (USB_HostState == HOST_STATE_Unattached)\r
return PIPE_READYWAIT_DeviceDisconnected;\r
\r
if (USB_INT_HasOccurred(USB_INT_HSOFI))\r
\r
Endpoint_ClearOUT();\r
}\r
+\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected;\r
}\r
\r
- while (!(Endpoint_IsINReady()));\r
+ while (!(Endpoint_IsINReady()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected;\r
+ }\r
\r
return ENDPOINT_RWCSTREAM_NoError;\r
}\r
\r
while (Length && !(Endpoint_IsOUTReceived()))\r
{\r
- while (!(Endpoint_IsINReady()));\r
+ while (!(Endpoint_IsINReady()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected;\r
+ }\r
\r
while (Length && (Endpoint_BytesInEndpoint() < USB_ControlEndpointSize))\r
{\r
\r
if (LastPacketFull)\r
{\r
- while (!(Endpoint_IsINReady()));\r
+ while (!(Endpoint_IsINReady()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected; \r
+ }\r
+ \r
Endpoint_ClearIN();\r
}\r
\r
- while (!(Endpoint_IsOUTReceived()));\r
+ while (!(Endpoint_IsOUTReceived()))\r
+ {\r
+ if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected; \r
+ }\r
\r
return ENDPOINT_RWCSTREAM_NoError;\r
}\r
* - Added new USE_FLASH_DESCRIPTORS and TOTAL_NUM_CONFIGURATIONS compile time options\r
* - Added support for the new ATMEGA32U2, ATMEGA16U2 and ATMEGA8U2 AVR models\r
* - Added new PrinterHost demo (thanks to John Andrews)\r
+ * - Added new USB_DeviceState variable to keep track of the current Device mode USB state\r
+ * - Added new Endpoint_ClearStatusStage() convenience function to assist with the status stages of control transfers\r
* \r
* <b>Changed:</b>\r
* - Deprecated psuedo-scheduler and removed dynamic memory allocator from the library (first no longer needed and second unused)\r
* descriptor is located can be specified. This means that descriptors can now be located in multiple memory spaces within a device.\r
* - Host mode demos now use sane terminal escape codes, so that text is always readable and events/program output is visually distinguished\r
* from oneanother using foreground colours\r
+ * - Removed vague USB_IsConnected global - test USB_DeviceState or USB_HostState explicitly to gain previous functionality\r
+ * - Removed USB_IsSuspended global - test USB_DeviceState against DEVICE_STATE_Suspended instead\r
*\r
* <b>Fixed:</b>\r
* - Changed bootloaders to use FLASHEND rather than the existence of RAMPZ to determine if far FLASH pointers are needed to fix\r
* LUFA/Drivers/USB/Class/ directory to LUFA/Drivers/USB/HighLevel/ in preperation for the new USB class APIs\r
* - Moved out each demos' functionality library files (e.g. Ring Buffer library) to /Lib directories for a better directory structure\r
* - Removed Tx interrupt from the USBtoSerial demo; now sends characters via polling to ensure more time for the Rx interrupt\r
+ * - Fixed possible enumeration errors from spinloops which may fail to exit if the USB connection is severed before the exit condition\r
+ * becomes true\r
*\r
*\r
* \section Sec_ChangeLog090510 Version 090510\r
* On the smaller USB AVRs, the USB controller lacks VBUS events to determine the physical connection state of the USB bus to a host. In lieu of\r
* VBUS events, the library attempts to determine the connection state via the bus suspension and wake up events instead. This however may be\r
* slightly inaccurate due to the possibility of the host suspending the bus while the device is still connected. If accurate connection status is\r
- * required, the VBUS line of the USB connector should be routed to an AVR pin to detect its level, so that the USB_IsConnected global\r
+ * required, the VBUS line of the USB connector should be routed to an AVR pin to detect its level, so that the USB_DeviceState global\r
* can be accurately set and the USB_Connect and USB_Disconnect events manually raised by the RAISE_EVENT macro. When defined, this token disables\r
* the library's auto-detection of the connection state by the aforementioned suspension and wake up events.\r
*\r
* - The "Dynamic Memory Block Allocator" has been removed, as it was unused in (and unrelated to) the LUFA library and never\r
* used in user applications. The library is available from the author's website for those wishing to still use it in their\r
* applications.\r
+ * - The USB_IsConnected global has been removed, as it is too vague for general use. Test \ref USB_DeviceState or \ref USB_HostState\r
+ * explicitly to ensure the device is in the desired state instead.\r
*\r
* <b>Host Mode</b>\r
* - The HIDParser.c module has moved from LUFA/Drivers/USB/Class/ to LUFA/Drivers/USB/Class/Host/.\r
- * - The USB_GetDeviceConfigDescriptor() function now requires the desired configuration index within the device as its first\r
+ * - The \ref USB_GetDeviceConfigDescriptor() function now requires the desired configuration index within the device as its first\r
* parameter, to add support for multi-configuration devices. Existing code should use a configuration index of 1 to indicate the\r
* first configuration descriptor within the device.\r
+ * - The non-standard "Ready" host state has been removed. Existing \ref HOST_STATE_Configured code should be moved to the end of\r
+ * the existing \ref HOST_STATE_Addressed state, and the existing HOST_STATE_Ready state code should be moved to the \ref HOST_STATE_Configured\r
+ * state.\r
*\r
* <b>Device Mode</b>\r
* - The \ref CALLBACK_USB_GetDescriptor() function now takes an extra parameter to specify the descriptor's memory space so that\r
* descriptors in mixed memory spaces can be used. The previous functionality can be returned by defining the USE_FLASH_DESCRIPTORS\r
* token in the project makefile to fix all descriptors into FLASH space and remove the extra function parameter.\r
+ * - Removed USB_IsSuspended - test \ref USB_DeviceState against \ref DEVICE_STATE_Suspended instead.\r
*\r
*\r
* \section Sec_Migration090605 Migrating from 090510 to 090605\r
USB_HostState = HOST_STATE_Configured;\r
break;\r
case HOST_STATE_Configured:\r
- USB_HostState = HOST_STATE_Ready;\r
- break;\r
- case HOST_STATE_Ready:\r
DiscardNextReport();\r
\r
break;\r