aboutsummaryrefslogtreecommitdiffstats
path: root/LUFA/Drivers
diff options
context:
space:
mode:
authorDean Camera <dean@fourwalledcubicle.com>2009-07-21 13:31:21 +0000
committerDean Camera <dean@fourwalledcubicle.com>2009-07-21 13:31:21 +0000
commite071f3897a0946c6be1e1b5e1f78eda8dcbf6fc7 (patch)
tree51ac5c80564fd76c93a357ee4d52a347384ac84b /LUFA/Drivers
parent44179abcf85acb14fb3aff72ce50ae84281c0f2e (diff)
downloadlufa-e071f3897a0946c6be1e1b5e1f78eda8dcbf6fc7.tar.gz
lufa-e071f3897a0946c6be1e1b5e1f78eda8dcbf6fc7.tar.bz2
lufa-e071f3897a0946c6be1e1b5e1f78eda8dcbf6fc7.zip
Added new USB_DeviceState variable to keep track of the current Device mode USB state.
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.
Diffstat (limited to 'LUFA/Drivers')
-rw-r--r--LUFA/Drivers/USB/Class/Device/Audio.c3
-rw-r--r--LUFA/Drivers/USB/Class/Device/CDC.c27
-rw-r--r--LUFA/Drivers/USB/Class/Device/HID.c14
-rw-r--r--LUFA/Drivers/USB/Class/Device/MIDI.c4
-rw-r--r--LUFA/Drivers/USB/Class/Device/MassStorage.c11
-rw-r--r--LUFA/Drivers/USB/Class/Device/RNDIS.c2
-rw-r--r--LUFA/Drivers/USB/HighLevel/Events.h4
-rw-r--r--LUFA/Drivers/USB/HighLevel/USBInterrupt.c52
-rw-r--r--LUFA/Drivers/USB/HighLevel/USBTask.c8
-rw-r--r--LUFA/Drivers/USB/HighLevel/USBTask.h61
-rw-r--r--LUFA/Drivers/USB/LowLevel/DevChapter9.c40
-rw-r--r--LUFA/Drivers/USB/LowLevel/Device.h31
-rw-r--r--LUFA/Drivers/USB/LowLevel/Endpoint.c26
-rw-r--r--LUFA/Drivers/USB/LowLevel/Endpoint.h45
-rw-r--r--LUFA/Drivers/USB/LowLevel/Host.c27
-rw-r--r--LUFA/Drivers/USB/LowLevel/Host.h26
-rw-r--r--LUFA/Drivers/USB/LowLevel/LowLevel.c25
-rw-r--r--LUFA/Drivers/USB/LowLevel/Pipe.c2
-rw-r--r--LUFA/Drivers/USB/LowLevel/Template/Template_Endpoint_Control_R.c9
-rw-r--r--LUFA/Drivers/USB/LowLevel/Template/Template_Endpoint_Control_W.c19
20 files changed, 278 insertions, 158 deletions
diff --git a/LUFA/Drivers/USB/Class/Device/Audio.c b/LUFA/Drivers/USB/Class/Device/Audio.c
index d117bedf6..116921e6e 100644
--- a/LUFA/Drivers/USB/Class/Device/Audio.c
+++ b/LUFA/Drivers/USB/Class/Device/Audio.c
@@ -50,8 +50,7 @@ void Audio_Device_ProcessControlPacket(USB_ClassInfo_Audio_Device_t* const Audio
AudioInterfaceInfo->State.InterfaceEnabled = (USB_ControlRequest.wValue != 0);
- while (!(Endpoint_IsINReady()));
- Endpoint_ClearIN();
+ Endpoint_ClearStatusStage();
}
break;
diff --git a/LUFA/Drivers/USB/Class/Device/CDC.c b/LUFA/Drivers/USB/Class/Device/CDC.c
index 12b55938c..237e1dd2f 100644
--- a/LUFA/Drivers/USB/Class/Device/CDC.c
+++ b/LUFA/Drivers/USB/Class/Device/CDC.c
@@ -78,8 +78,7 @@ void CDC_Device_ProcessControlPacket(USB_ClassInfo_CDC_Device_t* CDCInterfaceInf
EVENT_CDC_Device_ControLineStateChanged(CDCInterfaceInfo);
- while (!(Endpoint_IsINReady()));
- Endpoint_ClearIN();
+ Endpoint_ClearStatusStage();
}
break;
@@ -114,7 +113,7 @@ bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo)
void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo)
{
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))
+ if (USB_DeviceState != DEVICE_STATE_Configured)
return;
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);
@@ -125,7 +124,12 @@ void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo)
if (!(Endpoint_IsReadWriteAllowed()))
{
Endpoint_ClearIN();
- while (!(Endpoint_IsReadWriteAllowed()));
+
+ while (!(Endpoint_IsReadWriteAllowed()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
}
Endpoint_ClearIN();
@@ -133,7 +137,7 @@ void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo)
void CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, char* const Data, const uint16_t Length)
{
- if (!(USB_IsConnected))
+ if (USB_DeviceState != DEVICE_STATE_Configured)
return;
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);
@@ -142,7 +146,7 @@ void CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, c
void CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, const uint8_t Data)
{
- if (!(USB_IsConnected))
+ if (USB_DeviceState != DEVICE_STATE_Configured)
return;
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);
@@ -150,7 +154,12 @@ void CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, con
if (!(Endpoint_IsReadWriteAllowed()))
{
Endpoint_ClearIN();
- while (!(Endpoint_IsReadWriteAllowed()));
+
+ while (!(Endpoint_IsReadWriteAllowed()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
}
Endpoint_Write_Byte(Data);
@@ -165,7 +174,7 @@ uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterface
uint8_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo)
{
- if (!(USB_IsConnected))
+ if (USB_DeviceState != DEVICE_STATE_Configured)
return 0;
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber);
@@ -180,7 +189,7 @@ uint8_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo)
void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
{
- if (!(USB_IsConnected))
+ if (USB_DeviceState != DEVICE_STATE_Configured)
return;
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.NotificationEndpointNumber);
diff --git a/LUFA/Drivers/USB/Class/Device/HID.c b/LUFA/Drivers/USB/Class/Device/HID.c
index 4a6295ab0..f292c633e 100644
--- a/LUFA/Drivers/USB/Class/Device/HID.c
+++ b/LUFA/Drivers/USB/Class/Device/HID.c
@@ -88,8 +88,7 @@ void HID_Device_ProcessControlPacket(USB_ClassInfo_HID_Device_t* const HIDInterf
Endpoint_Write_Byte(HIDInterfaceInfo->State.UsingReportProtocol);
Endpoint_ClearIN();
- while (!(Endpoint_IsOUTReceived()));
- Endpoint_ClearOUT();
+ Endpoint_ClearStatusStage();
}
break;
@@ -100,8 +99,7 @@ void HID_Device_ProcessControlPacket(USB_ClassInfo_HID_Device_t* const HIDInterf
HIDInterfaceInfo->State.UsingReportProtocol = (USB_ControlRequest.wValue != 0x0000);
- while (!(Endpoint_IsINReady()));
- Endpoint_ClearIN();
+ Endpoint_ClearStatusStage();
}
break;
@@ -115,8 +113,7 @@ void HID_Device_ProcessControlPacket(USB_ClassInfo_HID_Device_t* const HIDInterf
HIDInterfaceInfo->State.IdleCount = ((USB_ControlRequest.wValue & 0xFF00) >> 6);
- while (!(Endpoint_IsINReady()));
- Endpoint_ClearIN();
+ Endpoint_ClearStatusStage();
}
}
@@ -129,8 +126,7 @@ void HID_Device_ProcessControlPacket(USB_ClassInfo_HID_Device_t* const HIDInterf
Endpoint_Write_Byte(HIDInterfaceInfo->State.IdleCount >> 2);
Endpoint_ClearIN();
- while (!(Endpoint_IsOUTReceived()));
- Endpoint_ClearOUT();
+ Endpoint_ClearStatusStage();
}
break;
@@ -152,7 +148,7 @@ bool HID_Device_ConfigureEndpoints(USB_ClassInfo_HID_Device_t* const HIDInterfac
void HID_Device_USBTask(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo)
{
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))
+ if (USB_DeviceState != DEVICE_STATE_Configured)
return;
Endpoint_SelectEndpoint(HIDInterfaceInfo->Config.ReportINEndpointNumber);
diff --git a/LUFA/Drivers/USB/Class/Device/MIDI.c b/LUFA/Drivers/USB/Class/Device/MIDI.c
index da33bdb61..364327595 100644
--- a/LUFA/Drivers/USB/Class/Device/MIDI.c
+++ b/LUFA/Drivers/USB/Class/Device/MIDI.c
@@ -70,7 +70,7 @@ void MIDI_Device_USBTask(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo)
void MIDI_Device_SendEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, MIDI_EventPacket_t* const Event)
{
- if (!(USB_IsConnected))
+ if (USB_DeviceState != DEVICE_STATE_Configured)
return;
Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpointNumber);
@@ -84,7 +84,7 @@ void MIDI_Device_SendEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfac
bool MIDI_Device_ReceiveEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, MIDI_EventPacket_t* const Event)
{
- if (!(USB_IsConnected))
+ if (USB_DeviceState != DEVICE_STATE_Configured)
return false;
Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataOUTEndpointNumber);
diff --git a/LUFA/Drivers/USB/Class/Device/MassStorage.c b/LUFA/Drivers/USB/Class/Device/MassStorage.c
index f7f3fd9f2..9f8688c1d 100644
--- a/LUFA/Drivers/USB/Class/Device/MassStorage.c
+++ b/LUFA/Drivers/USB/Class/Device/MassStorage.c
@@ -53,8 +53,7 @@ void MS_Device_ProcessControlPacket(USB_ClassInfo_MS_Device_t* const MSInterface
MSInterfaceInfo->State.IsMassStoreReset = true;
- while (!(Endpoint_IsINReady()));
- Endpoint_ClearIN();
+ Endpoint_ClearStatusStage();
}
break;
@@ -63,12 +62,10 @@ void MS_Device_ProcessControlPacket(USB_ClassInfo_MS_Device_t* const MSInterface
{
Endpoint_ClearSETUP();
- Endpoint_Write_Byte(MSInterfaceInfo->Config.TotalLUNs - 1);
-
+ Endpoint_Write_Byte(MSInterfaceInfo->Config.TotalLUNs - 1);
Endpoint_ClearIN();
- while (!(Endpoint_IsOUTReceived()));
- Endpoint_ClearOUT();
+ Endpoint_ClearStatusStage();
}
break;
@@ -96,7 +93,7 @@ bool MS_Device_ConfigureEndpoints(USB_ClassInfo_MS_Device_t* const MSInterfaceIn
void MS_Device_USBTask(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))
+ if (USB_DeviceState != DEVICE_STATE_Configured)
return;
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);
diff --git a/LUFA/Drivers/USB/Class/Device/RNDIS.c b/LUFA/Drivers/USB/Class/Device/RNDIS.c
index 0d35ee6b4..37771c646 100644
--- a/LUFA/Drivers/USB/Class/Device/RNDIS.c
+++ b/LUFA/Drivers/USB/Class/Device/RNDIS.c
@@ -138,7 +138,7 @@ bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t* const RNDISIn
void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
{
- if (!(USB_IsConnected) || !(USB_ConfigurationNumber))
+ if (USB_DeviceState != DEVICE_STATE_Configured)
return;
RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
diff --git a/LUFA/Drivers/USB/HighLevel/Events.h b/LUFA/Drivers/USB/HighLevel/Events.h
index 2df0dda08..4042d4670 100644
--- a/LUFA/Drivers/USB/HighLevel/Events.h
+++ b/LUFA/Drivers/USB/HighLevel/Events.h
@@ -98,7 +98,7 @@
* which is not always accurate (host may suspend the bus while still connected). If the actual connection state
* needs to be determined, VBUS should be routed to an external pin, and the auto-detect behaviour turned off by
* passing the NO_LIMITED_CONTROLLER_CONNECT token to the compiler via the -D switch at compile time. The connection
- * and disconnection events may be manually fired, and the \ref USB_IsConnected global changed manually.
+ * and disconnection events may be manually fired, and the \ref USB_DeviceState global changed manually.
*
* \see USBTask.h for more information on the USB management task and reducing CPU usage.
*/
@@ -116,7 +116,7 @@
* which is not always accurate (host may suspend the bus while still connected). If the actual connection state
* needs to be determined, VBUS should be routed to an external pin, and the auto-detect behaviour turned off by
* passing the NO_LIMITED_CONTROLLER_CONNECT token to the compiler via the -D switch at compile time. The connection
- * and disconnection events may be manually fired, and the \ref USB_IsConnected global changed manually.
+ * and disconnection events may be manually fired, and the \ref USB_DeviceState global changed manually.
*
* \see USBTask.h for more information on the USB management task and reducing CPU usage.
*/
diff --git a/LUFA/Drivers/USB/HighLevel/USBInterrupt.c b/LUFA/Drivers/USB/HighLevel/USBInterrupt.c
index c240bef6e..5edefa996 100644
--- a/LUFA/Drivers/USB/HighLevel/USBInterrupt.c
+++ b/LUFA/Drivers/USB/HighLevel/USBInterrupt.c
@@ -78,19 +78,17 @@ ISR(USB_GEN_vect, ISR_BLOCK)
{
EVENT_USB_VBUSConnect();
- if (USB_IsConnected)
+ if (USB_DeviceState != DEVICE_STATE_Unattached)
EVENT_USB_Disconnect();
USB_ResetInterface();
-
- USB_IsConnected = true;
+ USB_DeviceState = DEVICE_STATE_Powered;
EVENT_USB_Connect();
}
else
{
- USB_IsConnected = false;
-
+ USB_DeviceState = DEVICE_STATE_Unattached;
EVENT_USB_Disconnect();
USB_Detach();
@@ -117,16 +115,12 @@ ISR(USB_GEN_vect, ISR_BLOCK)
if (!(USB_Options & USB_OPT_MANUAL_PLL))
USB_PLL_Off();
- USB_IsSuspended = true;
-
- EVENT_USB_Suspend();
-
#if defined(USB_SERIES_2_AVR) && !defined(NO_LIMITED_CONTROLLER_CONNECT)
- if (USB_IsConnected)
- {
- USB_IsConnected = false;
- EVENT_USB_Disconnect();
- }
+ USB_DeviceState = DEVICE_STATE_Unattached;
+ EVENT_USB_Disconnect();
+ #else
+ USB_DeviceState = DEVICE_STATE_Suspended;
+ EVENT_USB_Suspend();
#endif
}
@@ -146,22 +140,19 @@ ISR(USB_GEN_vect, ISR_BLOCK)
USB_INT_Enable(USB_INT_SUSPEND);
#if defined(USB_SERIES_2_AVR) && !defined(NO_LIMITED_CONTROLLER_CONNECT)
- if (!(USB_IsConnected))
- {
- USB_IsConnected = true;
- EVENT_USB_Connect();
- }
+ USB_DeviceState = DEVICE_STATE_Powered;
+ EVENT_USB_Connect();
+ #else
+ USB_DeviceState = DEVICE_STATE_Configured;
+ EVENT_USB_WakeUp();
#endif
-
- USB_IsSuspended = false;
-
- EVENT_USB_WakeUp();
}
if (USB_INT_HasOccurred(USB_INT_EORSTI) && USB_INT_IsEnabled(USB_INT_EORSTI))
{
USB_INT_Clear(USB_INT_EORSTI);
+ USB_DeviceState = DEVICE_STATE_Default;
USB_ConfigurationNumber = 0;
USB_INT_Clear(USB_INT_SUSPEND);
@@ -217,7 +208,7 @@ ISR(USB_GEN_vect, ISR_BLOCK)
USB_INT_Enable(USB_INT_DDISCI);
- USB_HostState = HOST_STATE_Attached;
+ USB_HostState = HOST_STATE_Powered;
}
if (USB_INT_HasOccurred(USB_INT_BCERRI) && USB_INT_IsEnabled(USB_INT_BCERRI))
@@ -227,7 +218,7 @@ ISR(USB_GEN_vect, ISR_BLOCK)
EVENT_USB_DeviceEnumerationFailed(HOST_ENUMERROR_NoDeviceDetected, 0);
EVENT_USB_DeviceUnattached();
- if (USB_IsConnected)
+ if (USB_HostState != HOST_STATE_Unattached)
EVENT_USB_Disconnect();
USB_ResetInterface();
@@ -239,13 +230,16 @@ ISR(USB_GEN_vect, ISR_BLOCK)
{
USB_INT_Clear(USB_INT_IDTI);
- if (USB_IsConnected)
- {
- if (USB_CurrentMode == USB_MODE_HOST)
- EVENT_USB_DeviceUnattached();
+ if (USB_DeviceState != DEVICE_STATE_Unattached)
+ EVENT_USB_Disconnect();
+ if (USB_HostState != HOST_STATE_Unattached)
+ {
EVENT_USB_Disconnect();
+ EVENT_USB_DeviceUnattached();
}
+
+ EVENT_USB_Disconnect();
EVENT_USB_UIDChange();
diff --git a/LUFA/Drivers/USB/HighLevel/USBTask.c b/LUFA/Drivers/USB/HighLevel/USBTask.c
index 894171f24..500a697bc 100644
--- a/LUFA/Drivers/USB/HighLevel/USBTask.c
+++ b/LUFA/Drivers/USB/HighLevel/USBTask.c
@@ -33,8 +33,6 @@
#define INCLUDE_FROM_USBTASK_C
#include "USBTask.h"
-volatile bool USB_IsSuspended;
-volatile bool USB_IsConnected;
volatile bool USB_IsInitialized;
USB_Request_Header_t USB_ControlRequest;
@@ -42,6 +40,10 @@ USB_Request_Header_t USB_ControlRequest;
volatile uint8_t USB_HostState;
#endif
+#if defined(USB_CAN_BE_DEVICE)
+volatile uint8_t USB_DeviceState;
+#endif
+
void USB_USBTask(void)
{
#if defined(USB_HOST_ONLY)
@@ -59,7 +61,7 @@ void USB_USBTask(void)
#if defined(USB_CAN_BE_DEVICE)
static void USB_DeviceTask(void)
{
- if (USB_IsConnected)
+ if (USB_DeviceState != DEVICE_STATE_Unattached)
{
uint8_t PrevEndpoint = Endpoint_GetCurrentEndpoint();
diff --git a/LUFA/Drivers/USB/HighLevel/USBTask.h b/LUFA/Drivers/USB/HighLevel/USBTask.h
index 2a9bf1953..12acb1195 100644
--- a/LUFA/Drivers/USB/HighLevel/USBTask.h
+++ b/LUFA/Drivers/USB/HighLevel/USBTask.h
@@ -55,23 +55,6 @@
/* Public Interface - May be used in end-application: */
/* Global Variables: */
- /** Indicates if the USB interface is currently connected to a host if in device mode, or to a
- * device while running in host mode.
- *
- * \note This variable should be treated as read-only in the user application, and never manually
- * changed in value.
- *
- * \note For the smaller USB AVRs (AT90USBXX2) with limited USB controllers, VBUS is not available to the USB controller.
- * this means that the current connection state is derived from the bus suspension and wake up events by default,
- * which is not always accurate (host may suspend the bus while still connected). If the actual connection state
- * needs to be determined, VBUS should be routed to an external pin, and the auto-detect behaviour turned off by
- * passing the NO_LIMITED_CONTROLLER_CONNECT token to the compiler via the -D switch at compile time. The connection
- * and disconnection events may be manually fired, and the \ref USB_IsConnected global changed manually.
- *
- * \ingroup Group_USBManagement
- */
- extern volatile bool USB_IsConnected;
-
/** Indicates if the USB interface is currently initialized but not necessarily connected to a host
* or device (i.e. if \ref USB_Init() has been run). If this is false, all other library globals are invalid.
*
@@ -90,39 +73,43 @@
*/
extern USB_Request_Header_t USB_ControlRequest;
- #if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__)
- /** Indicates if the USB interface is currently suspended by the host when in device mode. When suspended,
- * the device should consume minimal power, and cannot communicate to the host. If Remote Wakeup is
- * supported by the device and \ref USB_RemoteWakeupEnabled is true, suspension can be terminated by the device
- * by issuing a Remote Wakeup request.
- *
- * \note This global is only present if the user application can be a USB device.
- *
- * \note This variable should be treated as read-only in the user application, and never manually
- * changed in value.
- *
- * \ingroup Group_Device
- */
- extern volatile bool USB_IsSuspended;
- #endif
-
#if defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__)
/** Indicates the current host state machine state. When in host mode, this indicates the state
- * via one of the values of the \ref USB_Host_States_t enum values in Host.h.
+ * via one of the values of the \ref USB_Host_States_t enum values.
*
* This value may be altered by the user application to implement the \ref HOST_STATE_Addressed,
- * \ref HOST_STATE_Configured, \ref HOST_STATE_Ready and \ref HOST_STATE_Suspended states which
- * are not implemented by the library.
+ * \ref HOST_STATE_Configured and \ref HOST_STATE_Suspended states which are not implemented by
+ * the library.
*
* \note This global is only present if the user application can be a USB host.
*
- * \see \ref USB_Host_States_t for a list of possible host states
+ * \see \ref USB_Host_States_t for a list of possible device states
*
* \ingroup Group_Host
*/
extern volatile uint8_t USB_HostState;
#endif
+ #if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__)
+ /** Indicates the current device state machine state. When in device mode, this indicates the state
+ * via one of the values of the \ref USB_Device_States_t enum values.
+ *
+ * This value should not be altered by the user application as it is handled automatically by the
+ * library. The only exception to this rule is if the NO_LIMITED_CONTROLLER_CONNECT token is used
+ * (see \ref EVENT_USB_Connect() and \ref EVENT_USB_Disconnect() events).
+ *
+ * \note This global is only present if the user application can be a USB device.
+ *
+ * \note This variable should be treated as read-only in the user application, and never manually
+ * changed in value except in the circumstances outlined above.
+ *
+ * \see \ref USB_Device_States_t for a list of possible device states
+ *
+ * \ingroup Group_Device
+ */
+ extern volatile uint8_t USB_DeviceState;
+ #endif
+
/* Function Prototypes: */
/** This is the main USB management task. The USB driver requires that this task be executed
* continuously when the USB system is active (device attached in host mode, or attached to a host
diff --git a/LUFA/Drivers/USB/LowLevel/DevChapter9.c b/LUFA/Drivers/USB/LowLevel/DevChapter9.c
index 10dce7298..8de4bd6a8 100644
--- a/LUFA/Drivers/USB/LowLevel/DevChapter9.c
+++ b/LUFA/Drivers/USB/LowLevel/DevChapter9.c
@@ -117,13 +117,22 @@ void USB_Device_ProcessControlPacket(void)
static void USB_Device_SetAddress(void)
{
+ uint8_t DeviceAddress = (USB_ControlRequest.wValue & 0x7F);
+
Endpoint_ClearSETUP();
Endpoint_ClearIN();
- while (!(Endpoint_IsINReady()));
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ UDADDR = ((1 << ADDEN) | DeviceAddress);
- UDADDR = ((1 << ADDEN) | ((uint8_t)USB_ControlRequest.wValue & 0x7F));
+ if (DeviceAddress)
+ USB_DeviceState = DEVICE_STATE_Addressed;
return;
}
@@ -185,8 +194,17 @@ static void USB_Device_SetConfiguration(void)
Endpoint_ClearIN();
- if (!(AlreadyConfigured) && USB_ConfigurationNumber)
- EVENT_USB_DeviceEnumerationComplete();
+ if (USB_ConfigurationNumber)
+ {
+ USB_DeviceState = DEVICE_STATE_Configured;
+
+ if (!(AlreadyConfigured))
+ EVENT_USB_DeviceEnumerationComplete();
+ }
+ else
+ {
+ USB_DeviceState = DEVICE_STATE_Addressed;
+ }
EVENT_USB_ConfigurationChanged();
}
@@ -199,7 +217,12 @@ void USB_Device_GetConfiguration(void)
Endpoint_ClearIN();
- while (!(Endpoint_IsOUTReceived()));
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
Endpoint_ClearOUT();
}
@@ -332,7 +355,12 @@ static void USB_Device_GetStatus(void)
Endpoint_ClearIN();
- while (!(Endpoint_IsOUTReceived()));
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
Endpoint_ClearOUT();
}
diff --git a/LUFA/Drivers/USB/LowLevel/Device.h b/LUFA/Drivers/USB/LowLevel/Device.h
index 975d09a79..e162a5980 100644
--- a/LUFA/Drivers/USB/LowLevel/Device.h
+++ b/LUFA/Drivers/USB/LowLevel/Device.h
@@ -118,7 +118,36 @@
#define USB_Device_IsUSBSuspended() ((UDINT & (1 << SUSPI)) ? true : false)
#endif
-
+
+ /* Type Defines: */
+ enum USB_Device_States_t
+ {
+ DEVICE_STATE_Unattached = 0, /**< Internally implemented by the library. This state indicates
+ * that the device is not currently connected to a host.
+ */
+ DEVICE_STATE_Powered = 1, /**< Internally implemented by the library. This state indicates
+ * that the device is connected to a host, but enumeration has not
+ * yet begun.
+ */
+ DEVICE_STATE_Default = 2, /**< Internally implemented by the library. This state indicates
+ * that the device's USB bus has been reset by the host and it is
+ * now waiting for the host to begin the enumeration process.
+ */
+ DEVICE_STATE_Addressed = 3, /**< Internally implemented by the library. This state indicates
+ * that the device has been addressed by the USB Host, but is not
+ * yet configured.
+ */
+ DEVICE_STATE_Configured = 4, /**< May be implemented by the user project. This state indicates
+ * that the device has been enumerated by the host and is ready
+ * for USB communications to begin.
+ */
+ DEVICE_STATE_Suspended = 5, /**< May be implemented by the user project. This state indicates
+ * that the USB bus has been suspended by the host, and the device
+ * should power down to a minimal power level until the bus is
+ * resumed.
+ */
+ };
+
/* Function Prototypes: */
/** Function to retrieve a given descriptor's size and memory location from the given descriptor type value,
* index and language ID. This function MUST be overridden in the user application (added with full, identical
diff --git a/LUFA/Drivers/USB/LowLevel/Endpoint.c b/LUFA/Drivers/USB/LowLevel/Endpoint.c
index f9db9cd22..e4d01404d 100644
--- a/LUFA/Drivers/USB/LowLevel/Endpoint.c
+++ b/LUFA/Drivers/USB/LowLevel/Endpoint.c
@@ -71,6 +71,30 @@ void Endpoint_ClearEndpoints(void)
}
}
+void Endpoint_ClearStatusStage(void)
+{
+ if (USB_ControlRequest.bmRequestType & REQDIR_DEVICETOHOST)
+ {
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ Endpoint_ClearOUT();
+ }
+ else
+ {
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ Endpoint_ClearIN();
+ }
+}
+
#if !defined(CONTROL_ONLY_DEVICE)
uint8_t Endpoint_WaitUntilReady(void)
{
@@ -93,7 +117,7 @@ uint8_t Endpoint_WaitUntilReady(void)
return ENDPOINT_READYWAIT_NoError;
}
- if (!(USB_IsConnected))
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
return ENDPOINT_READYWAIT_DeviceDisconnected;
else if (Endpoint_IsStalled())
return ENDPOINT_READYWAIT_EndpointStalled;
diff --git a/LUFA/Drivers/USB/LowLevel/Endpoint.h b/LUFA/Drivers/USB/LowLevel/Endpoint.h
index 2caea8343..a9ec122a2 100644
--- a/LUFA/Drivers/USB/LowLevel/Endpoint.h
+++ b/LUFA/Drivers/USB/LowLevel/Endpoint.h
@@ -431,14 +431,14 @@
ENDPOINT_RWSTREAM_EndpointStalled = 1, /**< The endpoint was stalled during the stream
* transfer by the host or device.
*/
- ENDPOINT_RWSTREAM_DeviceDisconnected = 1, /**< Device was disconnected from the host during
+ ENDPOINT_RWSTREAM_DeviceDisconnected = 2, /**< Device was disconnected from the host during
* the transfer.
*/
- ENDPOINT_RWSTREAM_Timeout = 2, /**< The host failed to accept or send the next packet
+ ENDPOINT_RWSTREAM_Timeout = 3, /**< The host failed to accept or send the next packet
* within the software timeout period set by the
* \ref USB_STREAM_TIMEOUT_MS macro.
*/
- ENDPOINT_RWSTREAM_CallbackAborted = 3, /**< Indicates that the stream's callback function
+ ENDPOINT_RWSTREAM_CallbackAborted = 4, /**< Indicates that the stream's callback function
* aborted the transfer early.
*/
};
@@ -451,6 +451,9 @@
{
ENDPOINT_RWCSTREAM_NoError = 0, /**< Command completed successfully, no error. */
ENDPOINT_RWCSTREAM_HostAborted = 1, /**< The aborted the transfer prematurely. */
+ ENDPOINT_RWCSTREAM_DeviceDisconnected = 2, /**< Device was disconnected from the host during
+ * the transfer.
+ */
};
/* Inline Functions: */
@@ -726,6 +729,12 @@
* \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum.
*/
uint8_t Endpoint_WaitUntilReady(void);
+
+ /** Completes the status stage of a control transfer on a CONTROL type endpoint automatically,
+ * with respect to the data direction. This is a convenience function which can be used to
+ * simplify user control request handling.
+ */
+ void Endpoint_ClearStatusStage(void);
/** Reads and discards the given number of bytes from the endpoint from the given buffer,
* discarding fully read packets from the host as needed. The last packet is not automatically
@@ -922,6 +931,9 @@
* in both failure and success states; the user is responsible for manually clearing the setup OUT to
* finalize the transfer via the \ref Endpoint_ClearOUT() macro.
*
+ * \note This function automatically clears the control transfer's status stage. Do not manually attempt
+ * to clear the status stage when using this routine in a control transaction.
+ *
* \note This routine should only be used on CONTROL type endpoints.
*
* \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
@@ -938,6 +950,9 @@
/** EEPROM buffer source version of Endpoint_Write_Control_Stream_LE.
*
+ * \note This function automatically clears the control transfer's status stage. Do not manually attempt
+ * to clear the status stage when using this routine in a control transaction.
+ *
* \note This routine should only be used on CONTROL type endpoints.
*
* \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
@@ -954,6 +969,9 @@
/** FLASH buffer source version of \ref Endpoint_Write_Control_Stream_LE.
*
+ * \note This function automatically clears the control transfer's status stage. Do not manually attempt
+ * to clear the status stage when using this routine in a control transaction.
+ *
* \note The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
*
* \note This routine should only be used on CONTROL type endpoints.
@@ -975,6 +993,9 @@
* in both failure and success states; the user is responsible for manually clearing the setup OUT to
* finalize the transfer via the \ref Endpoint_ClearOUT() macro.
*
+ * \note This function automatically clears the control transfer's status stage. Do not manually attempt
+ * to clear the status stage when using this routine in a control transaction.
+ *
* \note This routine should only be used on CONTROL type endpoints.
*
* \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
@@ -991,6 +1012,9 @@
/** EEPROM buffer source version of \ref Endpoint_Write_Control_Stream_BE.
*
+ * \note This function automatically clears the control transfer's status stage. Do not manually attempt
+ * to clear the status stage when using this routine in a control transaction.
+ *
* \note This routine should only be used on CONTROL type endpoints.
*
* \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
@@ -1007,6 +1031,9 @@
/** FLASH buffer source version of \ref Endpoint_Write_Control_Stream_BE.
*
+ * \note This function automatically clears the control transfer's status stage. Do not manually attempt
+ * to clear the status stage when using this routine in a control transaction.
+ *
* \note The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
*
* \note This routine should only be used on CONTROL type endpoints.
@@ -1028,6 +1055,9 @@
* automatically sent after success or failure states; the user is responsible for manually sending the
* setup IN to finalize the transfer via the \ref Endpoint_ClearIN() macro.
*
+ * \note This function automatically clears the control transfer's status stage. Do not manually attempt
+ * to clear the status stage when using this routine in a control transaction.
+ *
* \note This routine should only be used on CONTROL type endpoints.
*
* \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
@@ -1044,6 +1074,9 @@
/** EEPROM buffer source version of \ref Endpoint_Read_Control_Stream_LE.
*
+ * \note This function automatically clears the control transfer's status stage. Do not manually attempt
+ * to clear the status stage when using this routine in a control transaction.
+ *
* \note This routine should only be used on CONTROL type endpoints.
*
* \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
@@ -1063,6 +1096,9 @@
* automatically sent after success or failure states; the user is responsible for manually sending the
* setup IN to finalize the transfer via the \ref Endpoint_ClearIN() macro.
*
+ * \note This function automatically clears the control transfer's status stage. Do not manually attempt
+ * to clear the status stage when using this routine in a control transaction.
+ *
* \note This routine should only be used on CONTROL type endpoints.
*
* \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
@@ -1079,6 +1115,9 @@
/** EEPROM buffer source version of \ref Endpoint_Read_Control_Stream_BE.
*
+ * \note This function automatically clears the control transfer's status stage. Do not manually attempt
+ * to clear the status stage when using this routine in a control transaction.
+ *
* \note This routine should only be used on CONTROL type endpoints.
*
* \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
diff --git a/LUFA/Drivers/USB/LowLevel/Host.c b/LUFA/Drivers/USB/LowLevel/Host.c
index efe4baeeb..ae7525bee 100644
--- a/LUFA/Drivers/USB/LowLevel/Host.c
+++ b/LUFA/Drivers/USB/LowLevel/Host.c
@@ -60,12 +60,12 @@ void USB_Host_ProcessNextHostState(void)
}
break;
- case HOST_STATE_Attached:
+ case HOST_STATE_Powered:
WaitMSRemaining = HOST_DEVICE_SETTLE_DELAY_MS;
- USB_HostState = HOST_STATE_Attached_WaitForDeviceSettle;
+ USB_HostState = HOST_STATE_Powered_WaitForDeviceSettle;
break;
- case HOST_STATE_Attached_WaitForDeviceSettle:
+ case HOST_STATE_Powered_WaitForDeviceSettle:
#if HOST_DEVICE_SETTLE_DELAY_MS > 0
_delay_ms(1);
@@ -77,14 +77,14 @@ void USB_Host_ProcessNextHostState(void)
USB_Host_VBUS_Auto_Enable();
USB_Host_VBUS_Auto_On();
- USB_HostState = HOST_STATE_Attached_WaitForConnect;
+ USB_HostState = HOST_STATE_Powered_WaitForConnect;
}
#else
- USB_HostState = HOST_STATE_Attached_WaitForConnect;
+ USB_HostState = HOST_STATE_Powered_WaitForConnect;
#endif
break;
- case HOST_STATE_Attached_WaitForConnect:
+ case HOST_STATE_Powered_WaitForConnect:
if (USB_INT_HasOccurred(USB_INT_DCONNI))
{
USB_INT_Clear(USB_INT_DCONNI);
@@ -93,22 +93,21 @@ void USB_Host_ProcessNextHostState(void)
USB_INT_Clear(USB_INT_VBERRI);
USB_INT_Enable(USB_INT_VBERRI);
- USB_IsConnected = true;
EVENT_USB_Connect();
USB_Host_ResumeBus();
Pipe_ClearPipes();
- HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Attached_DoReset);
+ HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Powered_DoReset);
}
break;
- case HOST_STATE_Attached_DoReset:
+ case HOST_STATE_Powered_DoReset:
USB_Host_ResetDevice();
- HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Powered);
+ HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Powered_ConfigPipe);
break;
- case HOST_STATE_Powered:
+ case HOST_STATE_Powered_ConfigPipe:
Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL,
PIPE_TOKEN_SETUP, ENDPOINT_CONTROLEP,
PIPE_CONTROLPIPE_DEFAULT_SIZE, PIPE_BANK_SINGLE);
@@ -199,9 +198,7 @@ void USB_Host_ProcessNextHostState(void)
USB_Host_VBUS_Auto_Off();
EVENT_USB_DeviceUnattached();
-
- if (USB_IsConnected)
- EVENT_USB_Disconnect();
+ EVENT_USB_Disconnect();
USB_ResetInterface();
}
@@ -222,7 +219,7 @@ uint8_t USB_Host_WaitMS(uint8_t MS)
MS--;
}
- if ((USB_IsConnected == false) || (USB_CurrentMode == USB_MODE_DEVICE))
+ if ((USB_HostState == HOST_STATE_Unattached) || (USB_CurrentMode == USB_MODE_DEVICE))
{
ErrorCode = HOST_WAITERROR_DeviceDisconnect;
diff --git a/LUFA/Drivers/USB/LowLevel/Host.h b/LUFA/Drivers/USB/LowLevel/Host.h
index 88634fdae..a602cee77 100644
--- a/LUFA/Drivers/USB/LowLevel/Host.h
+++ b/LUFA/Drivers/USB/LowLevel/Host.h
@@ -241,32 +241,32 @@
*
* \note Do not manually change to this state in the user code.
*/
- HOST_STATE_Attached = 3, /**< Internally implemented by the library. This state indicates
+ HOST_STATE_Powered = 3, /**< Internally implemented by the library. This state indicates
* that a device has been attached, and the library's internals
* are being configured to begin the enumeration process.
*
* \note Do not manually change to this state in the user code.
*/
- HOST_STATE_Attached_WaitForDeviceSettle = 4, /**< Internally implemented by the library. This state indicates
+ HOST_STATE_Powered_WaitForDeviceSettle = 4, /**< Internally implemented by the library. This state indicates
* that the stack is waiting for the initial settling period to
* elapse before beginning the enumeration process.
*
* \note Do not manually change to this state in the user code.
*/
- HOST_STATE_Attached_WaitForConnect = 5, /**< Internally implemented by the library. This state indicates
+ HOST_STATE_Powered_WaitForConnect = 5, /**< Internally implemented by the library. This state indicates
* that the stack is waiting for a connection event from the USB
* controller to indicate a valid USB device has been attached to
* the bus and is ready to be enumerated.
*
* \note Do not manually change to this state in the user code.
*/
- HOST_STATE_Attached_DoReset = 6, /**< Internally implemented by the library. This state indicates
+ HOST_STATE_Powered_DoReset = 6, /**< Internally implemented by the library. This state indicates
* that a valid USB device has been attached, and that it is
* will now be reset to ensure it is ready for enumeration.
*
* \note Do not manually change to this state in the user code.
*/
- HOST_STATE_Powered = 7, /**< Internally implemented by the library. This state indicates
+ HOST_STATE_Powered_ConfigPipe = 7, /**< Internally implemented by the library. This state indicates
* that the attached device is currently powered and reset, and
* that the control pipe is now being configured by the stack.
*
@@ -301,20 +301,12 @@
* retrieval and processing of the device descriptor) should also
* be placed in this state.
*/
- HOST_STATE_Configured = 12, /**< May be implemented by the user project. This state should
- * implement any extra device configuration (such as the setting of
- * class-specific parameters) before normal communication is begun
- * in the HOST_STATE_Ready state.
- */
- HOST_STATE_Ready = 13, /**< May be implemented by the user project. This state should
- * contain the main communications with the attached device. From this
- * this state the host state machine should be changed to either
- * HOST_STATE_Suspended (after the bus is manually suspended using the
- * USB_Host_SuspendBus() macro) or HOST_STATE_WaitForDeviceRemoval as
- * needed.
+ HOST_STATE_Configured = 12, /**< May be implemented by the user project. This state should implement the
+ * actual work performed on the attached device and changed to the
+ * HOST_STATE_Suspended or HOST_STATE_WaitForDeviceRemoval states as needed.
*/
HOST_STATE_Suspended = 15, /**< May be implemented by the user project. This state should be maintained
- * while the bus is suspended, and changed to either the HOST_STATE_Ready
+ * while the bus is suspended, and changed to either the HOST_STATE_Configured
* (after resuming the bus with the USB_Host_ResumeBus() macro) or the
* HOST_STATE_WaitForDeviceRemoval states as needed.
*/
diff --git a/LUFA/Drivers/USB/LowLevel/LowLevel.c b/LUFA/Drivers/USB/LowLevel/LowLevel.c
index 4fcf4fcab..cd7fa891d 100644
--- a/LUFA/Drivers/USB/LowLevel/LowLevel.c
+++ b/LUFA/Drivers/USB/LowLevel/LowLevel.c
@@ -110,15 +110,21 @@ void USB_Init(
void USB_ShutDown(void)
{
- if (USB_IsConnected)
+ #if defined(USB_CAN_BE_DEVICE)
+ if (USB_DeviceState != DEVICE_STATE_Unattached)
+ EVENT_USB_Disconnect();
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ if (USB_HostState != HOST_STATE_Unattached)
EVENT_USB_Disconnect();
+ #endif
USB_Detach();
USB_INT_DisableAllInterrupts();
USB_INT_ClearAllInterrupts();
- USB_IsConnected = false;
USB_IsInitialized = false;
#if defined(USB_CAN_BE_HOST)
@@ -126,7 +132,10 @@ void USB_ShutDown(void)
#endif
#if defined(USB_CAN_BE_DEVICE)
- USB_ConfigurationNumber = 0;
+ USB_DeviceState = DEVICE_STATE_Unattached;
+ USB_ConfigurationNumber = 0;
+ USB_RemoteWakeupEnabled = false;
+ USB_CurrentlySelfPowered = false;
#endif
#if defined(CAN_BE_BOTH)
@@ -149,16 +158,14 @@ void USB_ResetInterface(void)
{
USB_INT_DisableAllInterrupts();
USB_INT_ClearAllInterrupts();
-
- USB_IsConnected = false;
-
+
#if defined(USB_CAN_BE_HOST)
- USB_HostState = HOST_STATE_Unattached;
+ USB_HostState = HOST_STATE_Unattached;
#endif
-
+
#if defined(USB_CAN_BE_DEVICE)
+ USB_DeviceState = DEVICE_STATE_Unattached;
USB_ConfigurationNumber = 0;
- USB_IsSuspended = false;
USB_RemoteWakeupEnabled = false;
USB_CurrentlySelfPowered = false;
#endif
diff --git a/LUFA/Drivers/USB/LowLevel/Pipe.c b/LUFA/Drivers/USB/LowLevel/Pipe.c
index 3fb30a2f7..7d3e87602 100644
--- a/LUFA/Drivers/USB/LowLevel/Pipe.c
+++ b/LUFA/Drivers/USB/LowLevel/Pipe.c
@@ -93,7 +93,7 @@ uint8_t Pipe_WaitUntilReady(void)
if (Pipe_IsStalled())
return PIPE_READYWAIT_PipeStalled;
- else if (!(USB_IsConnected))
+ else if (USB_HostState == HOST_STATE_Unattached)
return PIPE_READYWAIT_DeviceDisconnected;
if (USB_INT_HasOccurred(USB_INT_HSOFI))
diff --git a/LUFA/Drivers/USB/LowLevel/Template/Template_Endpoint_Control_R.c b/LUFA/Drivers/USB/LowLevel/Template/Template_Endpoint_Control_R.c
index d66edafd6..b85705c22 100644
--- a/LUFA/Drivers/USB/LowLevel/Template/Template_Endpoint_Control_R.c
+++ b/LUFA/Drivers/USB/LowLevel/Template/Template_Endpoint_Control_R.c
@@ -14,9 +14,16 @@ uint8_t TEMPLATE_FUNC_NAME (void* Buffer, uint16_t Length)
Endpoint_ClearOUT();
}
+
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected;
}
- while (!(Endpoint_IsINReady()));
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected;
+ }
return ENDPOINT_RWCSTREAM_NoError;
}
diff --git a/LUFA/Drivers/USB/LowLevel/Template/Template_Endpoint_Control_W.c b/LUFA/Drivers/USB/LowLevel/Template/Template_Endpoint_Control_W.c
index 2796c6425..43a9f3d42 100644
--- a/LUFA/Drivers/USB/LowLevel/Template/Template_Endpoint_Control_W.c
+++ b/LUFA/Drivers/USB/LowLevel/Template/Template_Endpoint_Control_W.c
@@ -8,7 +8,11 @@ uint8_t TEMPLATE_FUNC_NAME (void* Buffer, uint16_t Length)
while (Length && !(Endpoint_IsOUTReceived()))
{
- while (!(Endpoint_IsINReady()));
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected;
+ }
while (Length && (Endpoint_BytesInEndpoint() < USB_ControlEndpointSize))
{
@@ -25,11 +29,20 @@ uint8_t TEMPLATE_FUNC_NAME (void* Buffer, uint16_t Length)
if (LastPacketFull)
{
- while (!(Endpoint_IsINReady()));
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected;
+ }
+
Endpoint_ClearIN();
}
- while (!(Endpoint_IsOUTReceived()));
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected;
+ }
return ENDPOINT_RWCSTREAM_NoError;
}