From 7fbb75928749b74a0964ad159159066967191243 Mon Sep 17 00:00:00 2001
From: Dean Camera <dean@fourwalledcubicle.com>
Date: Mon, 31 Aug 2009 07:48:32 +0000
Subject: [PATCH] Changed the parameters and behaviour of the
 USB_GetDeviceConfigDescriptor() function so that it now performs size checks
 and data validations internally, to simplify user code.

---
 Demos/Host/ClassDriver/CDCHost/CDCHost.c      |  5 +--
 .../MassStorageHost/MassStorageHost.c         |  5 +--
 Demos/Host/ClassDriver/MouseHost/MouseHost.c  |  5 +--
 .../StillImageHost/StillImageHost.c           |  5 +--
 .../BluetoothHost/ConfigDescriptor.c          | 40 ++++++++----------
 .../BluetoothHost/DeviceDescriptor.c          |  3 +-
 .../Host/LowLevel/CDCHost/ConfigDescriptor.c  | 42 +++++++++----------
 .../GenericHIDHost/ConfigDescriptor.c         | 37 +++++++---------
 .../LowLevel/KeyboardHost/ConfigDescriptor.c  | 36 +++++++---------
 .../KeyboardHostWithParser/ConfigDescriptor.c | 38 ++++++++---------
 .../MassStorageHost/ConfigDescriptor.c        | 38 ++++++++---------
 .../LowLevel/MouseHost/ConfigDescriptor.c     | 36 +++++++---------
 .../MouseHostWithParser/ConfigDescriptor.c    | 38 ++++++++---------
 .../LowLevel/PrinterHost/ConfigDescriptor.c   | 39 +++++++----------
 .../StillImageHost/ConfigDescriptor.c         | 36 +++++++---------
 LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c | 39 +++++++++--------
 LUFA/Drivers/USB/HighLevel/ConfigDescriptor.h | 36 +++++++++++-----
 LUFA/ManPages/ChangeLog.txt                   |  2 +
 LUFA/ManPages/MigrationInformation.txt        |  6 +++
 19 files changed, 232 insertions(+), 254 deletions(-)

diff --git a/Demos/Host/ClassDriver/CDCHost/CDCHost.c b/Demos/Host/ClassDriver/CDCHost/CDCHost.c
index 7aa8deeee..4f67f3fbe 100644
--- a/Demos/Host/ClassDriver/CDCHost/CDCHost.c
+++ b/Demos/Host/ClassDriver/CDCHost/CDCHost.c
@@ -72,9 +72,8 @@ int main(void)
 				uint16_t ConfigDescriptorSize;
 				uint8_t  ConfigDescriptorData[512];
 
-				if ((USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, NULL) != HOST_SENDCONTROL_Successful) ||
-				    (ConfigDescriptorSize > sizeof(ConfigDescriptorData)) ||
-					(USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData)))
+				if (USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData,
+				                                  sizeof(ConfigDescriptorData)) != HOST_GETCONFIG_Successful)
 				{
 					printf("Error Retrieving Configuration Descriptor.\r\n");
 					LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
diff --git a/Demos/Host/ClassDriver/MassStorageHost/MassStorageHost.c b/Demos/Host/ClassDriver/MassStorageHost/MassStorageHost.c
index c9120d596..d22e07400 100644
--- a/Demos/Host/ClassDriver/MassStorageHost/MassStorageHost.c
+++ b/Demos/Host/ClassDriver/MassStorageHost/MassStorageHost.c
@@ -71,9 +71,8 @@ int main(void)
 				uint16_t ConfigDescriptorSize;
 				uint8_t  ConfigDescriptorData[512];
 
-				if ((USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, NULL) != HOST_SENDCONTROL_Successful) ||
-				    (ConfigDescriptorSize > sizeof(ConfigDescriptorData)) ||
-					(USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData)))
+				if (USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData,
+				                                  sizeof(ConfigDescriptorData)) != HOST_GETCONFIG_Successful)
 				{
 					printf("Error Retrieving Configuration Descriptor.\r\n");
 					LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
diff --git a/Demos/Host/ClassDriver/MouseHost/MouseHost.c b/Demos/Host/ClassDriver/MouseHost/MouseHost.c
index 9f76bc754..844fa334c 100644
--- a/Demos/Host/ClassDriver/MouseHost/MouseHost.c
+++ b/Demos/Host/ClassDriver/MouseHost/MouseHost.c
@@ -73,9 +73,8 @@ int main(void)
 				uint16_t ConfigDescriptorSize;
 				uint8_t  ConfigDescriptorData[512];
 
-				if ((USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, NULL) != HOST_SENDCONTROL_Successful) ||
-				    (ConfigDescriptorSize > sizeof(ConfigDescriptorData)) ||
-					(USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData)))
+				if (USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData,
+				                                  sizeof(ConfigDescriptorData)) != HOST_GETCONFIG_Successful)
 				{
 					printf("Error Retrieving Configuration Descriptor.\r\n");
 					LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
diff --git a/Demos/Host/ClassDriver/StillImageHost/StillImageHost.c b/Demos/Host/ClassDriver/StillImageHost/StillImageHost.c
index 2f0e5a2d1..deb8a5504 100644
--- a/Demos/Host/ClassDriver/StillImageHost/StillImageHost.c
+++ b/Demos/Host/ClassDriver/StillImageHost/StillImageHost.c
@@ -72,9 +72,8 @@ int main(void)
 				uint16_t ConfigDescriptorSize;
 				uint8_t  ConfigDescriptorData[512];
 
-				if ((USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, NULL) != HOST_SENDCONTROL_Successful) ||
-				    (ConfigDescriptorSize > sizeof(ConfigDescriptorData)) ||
-					(USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData)))
+				if (USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData,
+				                                  sizeof(ConfigDescriptorData)) != HOST_GETCONFIG_Successful)
 				{
 					printf("Error Retrieving Configuration Descriptor.\r\n");
 					LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
diff --git a/Demos/Host/Incomplete/BluetoothHost/ConfigDescriptor.c b/Demos/Host/Incomplete/BluetoothHost/ConfigDescriptor.c
index 948c4fcc6..f856262d6 100644
--- a/Demos/Host/Incomplete/BluetoothHost/ConfigDescriptor.c
+++ b/Demos/Host/Incomplete/BluetoothHost/ConfigDescriptor.c
@@ -32,34 +32,30 @@
 
 uint8_t ProcessConfigurationDescriptor(void)
 {
-	uint8_t* ConfigDescriptorData;
-	uint16_t ConfigDescriptorSize;
+	uint8_t  ConfigDescriptorData[512];
+	uint8_t* CurrConfigLocation = ConfigDescriptorData;
+	uint16_t CurrConfigBytesRem;
 	uint8_t  FoundEndpoints = 0;
-	
-	/* Get Configuration Descriptor size from the device */
-	if (USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, NULL) != HOST_SENDCONTROL_Successful)
-	  return ControlErrorDuringConfigRead;
-	
-	/* Ensure that the Configuration Descriptor isn't too large */
-	if (ConfigDescriptorSize > MAX_CONFIG_DESCRIPTOR_SIZE)
-	  return DescriptorTooLarge;
-	  
-	/* Allocate enough memory for the entire config descriptor */
-	ConfigDescriptorData = alloca(ConfigDescriptorSize);
 
 	/* Retrieve the entire configuration descriptor into the allocated buffer */
-	USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData);
+	switch (USB_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData)))
+	{
+		case HOST_GETCONFIG_Successful:
+			break;
+		case HOST_GETCONFIG_InvalidData:
+			return InvalidConfigDataReturned;
+		case HOST_GETCONFIG_BuffOverflow:
+			return DescriptorTooLarge;
+		default:
+			return ControlErrorDuringConfigRead;
+	}
 	
-	/* Validate returned data - ensure first entry is a configuration header descriptor */
-	if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
-	  return InvalidConfigDataReturned;
-
 	/* The bluetooth USB transport addendium mandates that the data (not streaming voice) endpoints
 	   be in the first interface descriptor (interface 0) */
-	USB_GetNextDescriptorOfType(&ConfigDescriptorSize, &ConfigDescriptorData, DTYPE_Interface);
+	USB_GetNextDescriptorOfType(&CurrConfigBytesRem, &CurrConfigLocation, DTYPE_Interface);
 	
 	/* Ensure that an interface was found, and the end of the descriptor was not reached */
-	if (!(ConfigDescriptorSize))
+	if (!(CurrConfigBytesRem))
 	  return NoInterfaceFound;
 
 	/* Get the data IN, data OUT and event notification endpoints for the bluetooth interface */
@@ -67,8 +63,8 @@ uint8_t ProcessConfigurationDescriptor(void)
 	                          (1 << BLUETOOTH_EVENTS_PIPE)))
 	{
 		/* Fetch the next endpoint from the current bluetooth interface */
-		if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
-		                                   NextInterfaceBluetoothDataEndpoint))
+		if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
+		                              NextInterfaceBluetoothDataEndpoint))
 		{
 			/* Descriptor not found, error out */
 			return NoEndpointFound;
diff --git a/Demos/Host/Incomplete/BluetoothHost/DeviceDescriptor.c b/Demos/Host/Incomplete/BluetoothHost/DeviceDescriptor.c
index f68f957c0..994352108 100644
--- a/Demos/Host/Incomplete/BluetoothHost/DeviceDescriptor.c
+++ b/Demos/Host/Incomplete/BluetoothHost/DeviceDescriptor.c
@@ -41,7 +41,8 @@ uint8_t ProcessDeviceDescriptor(void)
 	/* Validate returned data - ensure the returned data is a device descriptor */
 	if (DeviceDescriptor.Header.Type != DTYPE_Device)
 	  return InvalidDeviceDataReturned;
-	  
+	
+	/* Validate returned device Class, SubClass and Protocol values against the Bluetooth spec values */
 	if ((DeviceDescriptor.Class    != BLUETOOTH_DEVICE_CLASS)    ||
 	    (DeviceDescriptor.SubClass != BLUETOOTH_DEVICE_SUBCLASS) ||
 	    (DeviceDescriptor.Protocol != BLUETOOTH_DEVICE_PROTOCOL))
diff --git a/Demos/Host/LowLevel/CDCHost/ConfigDescriptor.c b/Demos/Host/LowLevel/CDCHost/ConfigDescriptor.c
index f1a57cd74..f9671e2b3 100644
--- a/Demos/Host/LowLevel/CDCHost/ConfigDescriptor.c
+++ b/Demos/Host/LowLevel/CDCHost/ConfigDescriptor.c
@@ -47,30 +47,26 @@
  */
 uint8_t ProcessConfigurationDescriptor(void)
 {
-	uint8_t* ConfigDescriptorData;
-	uint16_t ConfigDescriptorSize;
+	uint8_t  ConfigDescriptorData[512];
+	uint8_t* CurrConfigLocation = ConfigDescriptorData;
+	uint16_t CurrConfigBytesRem;
 	uint8_t  FoundEndpoints = 0;
-	
-	/* Get Configuration Descriptor size from the device */
-	if (USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, NULL) != HOST_SENDCONTROL_Successful)
-	  return ControlError;
-	
-	/* Ensure that the Configuration Descriptor isn't too large */
-	if (ConfigDescriptorSize > MAX_CONFIG_DESCRIPTOR_SIZE)
-	  return DescriptorTooLarge;
-	  
-	/* Allocate enough memory for the entire config descriptor */
-	ConfigDescriptorData = alloca(ConfigDescriptorSize);
 
 	/* Retrieve the entire configuration descriptor into the allocated buffer */
-	USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData);
-	
-	/* Validate returned data - ensure first entry is a configuration header descriptor */
-	if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
-	  return InvalidConfigDataReturned;
+	switch (USB_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData)))
+	{
+		case HOST_GETCONFIG_Successful:
+			break;
+		case HOST_GETCONFIG_InvalidData:
+			return InvalidConfigDataReturned;
+		case HOST_GETCONFIG_BuffOverflow:
+			return DescriptorTooLarge;
+		default:
+			return ControlError;
+	}
 	
 	/* Get the CDC control interface from the configuration descriptor */
-	if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+	if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
 	                              DComp_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
 	{
 		/* Descriptor not found, error out */
@@ -81,14 +77,14 @@ uint8_t ProcessConfigurationDescriptor(void)
 	while (FoundEndpoints != ((1 << CDC_NOTIFICATIONPIPE) | (1 << CDC_DATAPIPE_IN) | (1 << CDC_DATAPIPE_OUT)))
 	{
 		/* Fetch the next bulk or interrupt endpoint from the current CDC interface */
-		if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+		if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
 		                              DComp_NextInterfaceCDCDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
 		{
 			/* Check to see if the control interface's notification pipe has been found, if so search for the data interface */
 			if (FoundEndpoints & (1 << CDC_NOTIFICATIONPIPE))
 			{
 				/* Get the next CDC data interface from the configuration descriptor (CDC class has two CDC interfaces) */
-				if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, 
+				if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, 
 				                              DComp_NextCDCDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
 				{
 					/* Descriptor not found, error out */
@@ -109,7 +105,7 @@ uint8_t ProcessConfigurationDescriptor(void)
 				Pipe_DisablePipe();
 			
 				/* Get the next CDC control interface from the configuration descriptor (CDC class has two CDC interfaces) */
-				if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+				if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
 				                              DComp_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
 				{
 					/* Descriptor not found, error out */
@@ -118,7 +114,7 @@ uint8_t ProcessConfigurationDescriptor(void)
 			}
 
 			/* Fetch the next bulk or interrupt endpoint from the current CDC interface */
-			if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+			if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
 			                              DComp_NextInterfaceCDCDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
 			{
 				/* Descriptor not found, error out */
diff --git a/Demos/Host/LowLevel/GenericHIDHost/ConfigDescriptor.c b/Demos/Host/LowLevel/GenericHIDHost/ConfigDescriptor.c
index dbec62b63..dba62fd06 100644
--- a/Demos/Host/LowLevel/GenericHIDHost/ConfigDescriptor.c
+++ b/Demos/Host/LowLevel/GenericHIDHost/ConfigDescriptor.c
@@ -47,31 +47,26 @@
  */
 uint8_t ProcessConfigurationDescriptor(void)
 {
-	uint8_t* ConfigDescriptorData;
-	uint16_t ConfigDescriptorSize;
-	
+	uint8_t  ConfigDescriptorData[512];
+	uint8_t* CurrConfigLocation = ConfigDescriptorData;
+	uint16_t CurrConfigBytesRem;
 	uint8_t  FoundEndpoints = 0;
-	
-	/* Get Configuration Descriptor size from the device */
-	if (USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, NULL) != HOST_SENDCONTROL_Successful)
-	  return ControlError;
-	
-	/* Ensure that the Configuration Descriptor isn't too large */
-	if (ConfigDescriptorSize > MAX_CONFIG_DESCRIPTOR_SIZE)
-	  return DescriptorTooLarge;
-	  
-	/* Allocate enough memory for the entire config descriptor */
-	ConfigDescriptorData = alloca(ConfigDescriptorSize);
 
 	/* Retrieve the entire configuration descriptor into the allocated buffer */
-	USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData);
-	
-	/* Validate returned data - ensure first entry is a configuration header descriptor */
-	if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
-	  return InvalidConfigDataReturned;
+	switch (USB_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData)))
+	{
+		case HOST_GETCONFIG_Successful:
+			break;
+		case HOST_GETCONFIG_InvalidData:
+			return InvalidConfigDataReturned;
+		case HOST_GETCONFIG_BuffOverflow:
+			return DescriptorTooLarge;
+		default:
+			return ControlError;
+	}
 	
 	/* Get the HID interface from the configuration descriptor */
-	if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+	if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
 	                              DComp_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found)
 	{
 		/* Descriptor not found, error out */
@@ -81,7 +76,7 @@ uint8_t ProcessConfigurationDescriptor(void)
 	while (FoundEndpoints != ((1 << HID_DATA_IN_PIPE) | (1 << HID_DATA_OUT_PIPE)))
 	{
 		/* Get the next HID interface's data endpoint descriptor */
-		if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+		if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
 		                              DComp_NextInterfaceHIDDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
 		{
 			/* Not all HID devices have an OUT endpoint - if we've reached the end of the HID descriptor
diff --git a/Demos/Host/LowLevel/KeyboardHost/ConfigDescriptor.c b/Demos/Host/LowLevel/KeyboardHost/ConfigDescriptor.c
index 403306042..46fb94ee2 100644
--- a/Demos/Host/LowLevel/KeyboardHost/ConfigDescriptor.c
+++ b/Demos/Host/LowLevel/KeyboardHost/ConfigDescriptor.c
@@ -47,29 +47,25 @@
  */
 uint8_t ProcessConfigurationDescriptor(void)
 {
-	uint8_t* ConfigDescriptorData;
-	uint16_t ConfigDescriptorSize;
-	
-	/* Get Configuration Descriptor size from the device */
-	if (USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, NULL) != HOST_SENDCONTROL_Successful)
-	  return ControlError;
-	
-	/* Ensure that the Configuration Descriptor isn't too large */
-	if (ConfigDescriptorSize > MAX_CONFIG_DESCRIPTOR_SIZE)
-	  return DescriptorTooLarge;
-	  
-	/* Allocate enough memory for the entire config descriptor */
-	ConfigDescriptorData = alloca(ConfigDescriptorSize);
+	uint8_t  ConfigDescriptorData[512];
+	uint8_t* CurrConfigLocation = ConfigDescriptorData;
+	uint16_t CurrConfigBytesRem;
 
 	/* Retrieve the entire configuration descriptor into the allocated buffer */
-	USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData);
-	
-	/* Validate returned data - ensure first entry is a configuration header descriptor */
-	if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
-	  return InvalidConfigDataReturned;
+	switch (USB_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData)))
+	{
+		case HOST_GETCONFIG_Successful:
+			break;
+		case HOST_GETCONFIG_InvalidData:
+			return InvalidConfigDataReturned;
+		case HOST_GETCONFIG_BuffOverflow:
+			return DescriptorTooLarge;
+		default:
+			return ControlError;
+	}
 	
 	/* Get the keyboard interface from the configuration descriptor */
-	if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+	if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
 	                              DComp_NextKeyboardInterface) != DESCRIPTOR_SEARCH_COMP_Found)
 	{
 		/* Descriptor not found, error out */
@@ -77,7 +73,7 @@ uint8_t ProcessConfigurationDescriptor(void)
 	}
 
 	/* Get the keyboard interface's data endpoint descriptor */
-	if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+	if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
 	                              DComp_NextInterfaceKeyboardDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
 	{
 		/* Descriptor not found, error out */
diff --git a/Demos/Host/LowLevel/KeyboardHostWithParser/ConfigDescriptor.c b/Demos/Host/LowLevel/KeyboardHostWithParser/ConfigDescriptor.c
index d9fd50f69..7ab0a1887 100644
--- a/Demos/Host/LowLevel/KeyboardHostWithParser/ConfigDescriptor.c
+++ b/Demos/Host/LowLevel/KeyboardHostWithParser/ConfigDescriptor.c
@@ -47,29 +47,25 @@
  */
 uint8_t ProcessConfigurationDescriptor(void)
 {
-	uint8_t* ConfigDescriptorData;
-	uint16_t ConfigDescriptorSize;
-	
-	/* Get Configuration Descriptor size from the device */
-	if (USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, NULL) != HOST_SENDCONTROL_Successful)
-	  return ControlError;
-	
-	/* Ensure that the Configuration Descriptor isn't too large */
-	if (ConfigDescriptorSize > MAX_CONFIG_DESCRIPTOR_SIZE)
-	  return DescriptorTooLarge;
-	  
-	/* Allocate enough memory for the entire config descriptor */
-	ConfigDescriptorData = alloca(ConfigDescriptorSize);
+	uint8_t  ConfigDescriptorData[512];
+	uint8_t* CurrConfigLocation = ConfigDescriptorData;
+	uint16_t CurrConfigBytesRem;
 
 	/* Retrieve the entire configuration descriptor into the allocated buffer */
-	USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData);
-	
-	/* Validate returned data - ensure first entry is a configuration header descriptor */
-	if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
-	  return InvalidConfigDataReturned;
+	switch (USB_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData)))
+	{
+		case HOST_GETCONFIG_Successful:
+			break;
+		case HOST_GETCONFIG_InvalidData:
+			return InvalidConfigDataReturned;
+		case HOST_GETCONFIG_BuffOverflow:
+			return DescriptorTooLarge;
+		default:
+			return ControlError;
+	}
 	
 	/* Get the keyboard interface from the configuration descriptor */
-	if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+	if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
 	                              DComp_NextKeyboardInterface) != DESCRIPTOR_SEARCH_COMP_Found)
 	{
 		/* Descriptor not found, error out */
@@ -77,7 +73,7 @@ uint8_t ProcessConfigurationDescriptor(void)
 	}
 	
 	/* Get the keyboard interface's HID descriptor */
-	if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+	if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
 	                              DComp_NextHID) != DESCRIPTOR_SEARCH_COMP_Found)
 	{
 		/* Descriptor not found, error out */
@@ -88,7 +84,7 @@ uint8_t ProcessConfigurationDescriptor(void)
 	HIDReportSize = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_HID_t).HIDReportLength;
 
 	/* Get the keyboard interface's data endpoint descriptor */
-	if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+	if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
 	                              DComp_NextInterfaceKeyboardDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
 	{
 		/* Descriptor not found, error out */
diff --git a/Demos/Host/LowLevel/MassStorageHost/ConfigDescriptor.c b/Demos/Host/LowLevel/MassStorageHost/ConfigDescriptor.c
index 9f80b42ee..1ba3244ed 100644
--- a/Demos/Host/LowLevel/MassStorageHost/ConfigDescriptor.c
+++ b/Demos/Host/LowLevel/MassStorageHost/ConfigDescriptor.c
@@ -47,30 +47,26 @@
  */
 uint8_t ProcessConfigurationDescriptor(void)
 {
-	uint8_t* ConfigDescriptorData;
-	uint16_t ConfigDescriptorSize;
-	uint8_t  FoundEndpoints = 0;
-	
-	/* Get Configuration Descriptor size from the device */
-	if (USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, NULL) != HOST_SENDCONTROL_Successful)
-	  return ControlError;
-	
-	/* Ensure that the Configuration Descriptor isn't too large */
-	if (ConfigDescriptorSize > MAX_CONFIG_DESCRIPTOR_SIZE)
-	  return DescriptorTooLarge;
-	  
-	/* Allocate enough memory for the entire config descriptor */
-	ConfigDescriptorData = alloca(ConfigDescriptorSize);
+	uint8_t  ConfigDescriptorData[512];
+	uint8_t* CurrConfigLocation = ConfigDescriptorData;
+	uint16_t CurrConfigBytesRem;
+	uint8_t  FoundEndpoints     = 0;
 
 	/* Retrieve the entire configuration descriptor into the allocated buffer */
-	USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData);
-	
-	/* Validate returned data - ensure first entry is a configuration header descriptor */
-	if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
-	  return InvalidConfigDataReturned;
+	switch (USB_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData)))
+	{
+		case HOST_GETCONFIG_Successful:
+			break;
+		case HOST_GETCONFIG_InvalidData:
+			return InvalidConfigDataReturned;
+		case HOST_GETCONFIG_BuffOverflow:
+			return DescriptorTooLarge;
+		default:
+			return ControlError;
+	}
 	
 	/* Get the mass storage interface from the configuration descriptor */
-	if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+	if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
 	                              DComp_NextMassStorageInterface) != DESCRIPTOR_SEARCH_COMP_Found)
 	{
 		/* Descriptor not found, error out */
@@ -81,7 +77,7 @@ uint8_t ProcessConfigurationDescriptor(void)
 	while (FoundEndpoints != ((1 << MASS_STORE_DATA_IN_PIPE) | (1 << MASS_STORE_DATA_OUT_PIPE)))
 	{
 		/* Fetch the next bulk endpoint from the current mass storage interface */
-		if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+		if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
 		                              DComp_NextInterfaceBulkDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
 		{
 			/* Descriptor not found, error out */
diff --git a/Demos/Host/LowLevel/MouseHost/ConfigDescriptor.c b/Demos/Host/LowLevel/MouseHost/ConfigDescriptor.c
index e0be70b1b..912f146bc 100644
--- a/Demos/Host/LowLevel/MouseHost/ConfigDescriptor.c
+++ b/Demos/Host/LowLevel/MouseHost/ConfigDescriptor.c
@@ -47,29 +47,25 @@
  */
 uint8_t ProcessConfigurationDescriptor(void)
 {
-	uint8_t* ConfigDescriptorData;
-	uint16_t ConfigDescriptorSize;
-	
-	/* Get Configuration Descriptor size from the device */
-	if (USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, NULL) != HOST_SENDCONTROL_Successful)
-	  return ControlError;
-	
-	/* Ensure that the Configuration Descriptor isn't too large */
-	if (ConfigDescriptorSize > MAX_CONFIG_DESCRIPTOR_SIZE)
-	  return DescriptorTooLarge;
-	  
-	/* Allocate enough memory for the entire config descriptor */
-	ConfigDescriptorData = alloca(ConfigDescriptorSize);
+	uint8_t  ConfigDescriptorData[512];
+	uint8_t* CurrConfigLocation = ConfigDescriptorData;
+	uint16_t CurrConfigBytesRem;
 
 	/* Retrieve the entire configuration descriptor into the allocated buffer */
-	USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData);
-	
-	/* Validate returned data - ensure first entry is a configuration header descriptor */
-	if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
-	  return InvalidConfigDataReturned;
+	switch (USB_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData)))
+	{
+		case HOST_GETCONFIG_Successful:
+			break;
+		case HOST_GETCONFIG_InvalidData:
+			return InvalidConfigDataReturned;
+		case HOST_GETCONFIG_BuffOverflow:
+			return DescriptorTooLarge;
+		default:
+			return ControlError;
+	}
 	
 	/* Get the mouse interface from the configuration descriptor */
-	if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+	if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
 	                              DComp_NextMouseInterface) != DESCRIPTOR_SEARCH_COMP_Found)
 	{
 		/* Descriptor not found, error out */
@@ -77,7 +73,7 @@ uint8_t ProcessConfigurationDescriptor(void)
 	}
 
 	/* Get the mouse interface's data endpoint descriptor */
-	if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+	if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
 	                              DComp_NextInterfaceMouseDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
 	{
 		/* Descriptor not found, error out */
diff --git a/Demos/Host/LowLevel/MouseHostWithParser/ConfigDescriptor.c b/Demos/Host/LowLevel/MouseHostWithParser/ConfigDescriptor.c
index 1d28351ee..fa0674118 100644
--- a/Demos/Host/LowLevel/MouseHostWithParser/ConfigDescriptor.c
+++ b/Demos/Host/LowLevel/MouseHostWithParser/ConfigDescriptor.c
@@ -47,29 +47,25 @@
  */
 uint8_t ProcessConfigurationDescriptor(void)
 {
-	uint8_t* ConfigDescriptorData;
-	uint16_t ConfigDescriptorSize;
-	
-	/* Get Configuration Descriptor size from the device */
-	if (USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, NULL) != HOST_SENDCONTROL_Successful)
-	  return ControlError;
-	
-	/* Ensure that the Configuration Descriptor isn't too large */
-	if (ConfigDescriptorSize > MAX_CONFIG_DESCRIPTOR_SIZE)
-	  return DescriptorTooLarge;
-	  
-	/* Allocate enough memory for the entire config descriptor */
-	ConfigDescriptorData = alloca(ConfigDescriptorSize);
+	uint8_t  ConfigDescriptorData[512];
+	uint8_t* CurrConfigLocation = ConfigDescriptorData;
+	uint16_t CurrConfigBytesRem;
 
 	/* Retrieve the entire configuration descriptor into the allocated buffer */
-	USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData);
-	
-	/* Validate returned data - ensure first entry is a configuration header descriptor */
-	if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
-	  return InvalidConfigDataReturned;
+	switch (USB_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData)))
+	{
+		case HOST_GETCONFIG_Successful:
+			break;
+		case HOST_GETCONFIG_InvalidData:
+			return InvalidConfigDataReturned;
+		case HOST_GETCONFIG_BuffOverflow:
+			return DescriptorTooLarge;
+		default:
+			return ControlError;
+	}
 	
 	/* Get the mouse interface from the configuration descriptor */
-	if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+	if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
 	                              DComp_NextMouseInterface) != DESCRIPTOR_SEARCH_COMP_Found)
 	{
 		/* Descriptor not found, error out */
@@ -77,7 +73,7 @@ uint8_t ProcessConfigurationDescriptor(void)
 	}
 	
 	/* Get the mouse interface's HID descriptor */
-	if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+	if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
 	                              DComp_NextHID) != DESCRIPTOR_SEARCH_COMP_Found)
 	{
 		/* Descriptor not found, error out */
@@ -88,7 +84,7 @@ uint8_t ProcessConfigurationDescriptor(void)
 	HIDReportSize = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_HID_t).HIDReportLength;
 
 	/* Get the mouse interface's data endpoint descriptor */
-	if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+	if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
 	                              DComp_NextInterfaceMouseDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
 	{
 		/* Descriptor not found, error out */
diff --git a/Demos/Host/LowLevel/PrinterHost/ConfigDescriptor.c b/Demos/Host/LowLevel/PrinterHost/ConfigDescriptor.c
index d4eaff94a..22d84c5aa 100644
--- a/Demos/Host/LowLevel/PrinterHost/ConfigDescriptor.c
+++ b/Demos/Host/LowLevel/PrinterHost/ConfigDescriptor.c
@@ -36,32 +36,26 @@ uint8_t PrinterAltSetting;
 
 uint8_t ProcessConfigurationDescriptor(void)
 {
-	uint8_t* ConfigDescriptorData;
-	uint16_t ConfigDescriptorSize;
-	uint8_t  ErrorCode;
+	uint8_t  ConfigDescriptorData[512];
+	uint8_t* CurrConfigLocation = ConfigDescriptorData;
+	uint16_t CurrConfigBytesRem;
 	uint8_t  FoundEndpoints = 0;
-	
-	/* Get Configuration Descriptor size from the device */
-	if (USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, NULL) != HOST_SENDCONTROL_Successful)
-	  return ControlError;
-	
-	/* Ensure that the Configuration Descriptor isn't too large */
-	if (ConfigDescriptorSize > MAX_CONFIG_DESCRIPTOR_SIZE)
-	  return DescriptorTooLarge;
-	  
-	/* Allocate enough memory for the entire config descriptor */
-	ConfigDescriptorData = alloca(ConfigDescriptorSize);
 
 	/* Retrieve the entire configuration descriptor into the allocated buffer */
-	USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData);
-	
-	/* Validate returned data - ensure first entry is a configuration header descriptor */
-	if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
-	  return InvalidConfigDataReturned;
+	switch (USB_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData)))
+	{
+		case HOST_GETCONFIG_Successful:
+			break;
+		case HOST_GETCONFIG_InvalidData:
+			return InvalidConfigDataReturned;
+		case HOST_GETCONFIG_BuffOverflow:
+			return DescriptorTooLarge;
+		default:
+			return ControlError;
+	}
 	
 	/* Get the printer interface from the configuration descriptor */
-	if ((ErrorCode = USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
-	                                           DComp_NextBidirectionalPrinterInterface)))
+	if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextBidirectionalPrinterInterface))
 	{
 		/* Descriptor not found, error out */
 		return NoInterfaceFound;
@@ -74,8 +68,7 @@ uint8_t ProcessConfigurationDescriptor(void)
 	while (FoundEndpoints != ((1 << PRINTER_DATA_OUT_PIPE) | (1 << PRINTER_DATA_IN_PIPE)))
 	{
 		/* Fetch the next bulk endpoint from the current printer interface */
-		if ((ErrorCode = USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
-		                                           DComp_NextInterfaceBulkDataEndpoint)))
+		if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextInterfaceBulkDataEndpoint))
 		{
 			/* Descriptor not found, error out */
 			return NoEndpointFound;
diff --git a/Demos/Host/LowLevel/StillImageHost/ConfigDescriptor.c b/Demos/Host/LowLevel/StillImageHost/ConfigDescriptor.c
index a2d4d48dd..4e7751d71 100644
--- a/Demos/Host/LowLevel/StillImageHost/ConfigDescriptor.c
+++ b/Demos/Host/LowLevel/StillImageHost/ConfigDescriptor.c
@@ -47,30 +47,26 @@
  */
 uint8_t ProcessConfigurationDescriptor(void)
 {
-	uint8_t* ConfigDescriptorData;
-	uint16_t ConfigDescriptorSize;
+	uint8_t  ConfigDescriptorData[512];
+	uint8_t* CurrConfigLocation = ConfigDescriptorData;
+	uint16_t CurrConfigBytesRem;
 	uint8_t  FoundEndpoints = 0;
-	
-	/* Get Configuration Descriptor size from the device */
-	if (USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, NULL) != HOST_SENDCONTROL_Successful)
-	  return ControlError;
-	
-	/* Ensure that the Configuration Descriptor isn't too large */
-	if (ConfigDescriptorSize > MAX_CONFIG_DESCRIPTOR_SIZE)
-	  return DescriptorTooLarge;
-	  
-	/* Allocate enough memory for the entire config descriptor */
-	ConfigDescriptorData = alloca(ConfigDescriptorSize);
 
 	/* Retrieve the entire configuration descriptor into the allocated buffer */
-	USB_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData);
-	
-	/* Validate returned data - ensure first entry is a configuration header descriptor */
-	if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
-	  return InvalidConfigDataReturned;
+	switch (USB_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData)))
+	{
+		case HOST_GETCONFIG_Successful:
+			break;
+		case HOST_GETCONFIG_InvalidData:
+			return InvalidConfigDataReturned;
+		case HOST_GETCONFIG_BuffOverflow:
+			return DescriptorTooLarge;
+		default:
+			return ControlError;
+	}
 	
 	/* Get the Still Image interface from the configuration descriptor */
-	if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+	if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
 	                              DComp_NextStillImageInterface) != DESCRIPTOR_SEARCH_COMP_Found)
 	{
 		/* Descriptor not found, error out */
@@ -81,7 +77,7 @@ uint8_t ProcessConfigurationDescriptor(void)
 	while (FoundEndpoints != ((1 << SIMAGE_EVENTS_PIPE) | (1 << SIMAGE_DATA_IN_PIPE) | (1 << SIMAGE_DATA_OUT_PIPE)))
 	{
 		/* Fetch the next endpoint from the current Still Image interface */
-		if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+		if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
 		                              DComp_NextStillImageInterfaceDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
 		{
 			/* Descriptor not found, error out */
diff --git a/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c b/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c
index 47982b806..4c6fbfdab 100644
--- a/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c
+++ b/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c
@@ -31,9 +31,11 @@
 #include "ConfigDescriptor.h"
 
 #if defined(USB_CAN_BE_HOST)
-uint8_t USB_GetDeviceConfigDescriptor(uint8_t ConfigNumber, uint16_t* const ConfigSizePtr, void* BufferPtr)
+uint8_t USB_GetDeviceConfigDescriptor(uint8_t ConfigNumber, uint16_t* const ConfigSizePtr,
+                                      void* BufferPtr, uint16_t BufferSize)
 {
 	uint8_t ErrorCode;
+	uint8_t ConfigHeader[sizeof(USB_Descriptor_Configuration_Header_t)];
 
 	USB_ControlRequest = (USB_Request_Header_t)
 		{
@@ -46,26 +48,27 @@ uint8_t USB_GetDeviceConfigDescriptor(uint8_t ConfigNumber, uint16_t* const Conf
 	
 	Pipe_SelectPipe(PIPE_CONTROLPIPE);
 
-	if (BufferPtr == NULL)
-	{
-		uint8_t ConfigHeader[sizeof(USB_Descriptor_Configuration_Header_t)];
+	if ((ErrorCode = USB_Host_SendControlRequest(ConfigHeader)) != HOST_SENDCONTROL_Successful)
+	  return ErrorCode;
 
-		ErrorCode      = USB_Host_SendControlRequest(ConfigHeader);
+	#if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES)
+	*ConfigSizePtr = DESCRIPTOR_CAST(ConfigHeader, USB_Descriptor_Configuration_Header_t).TotalConfigurationSize;
+	#else
+	*ConfigSizePtr = DESCRIPTOR_CAST(ConfigHeader, USB_Descriptor_Configuration_Header_t).wTotalLength;		
+	#endif
 
-		#if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES)
-		*ConfigSizePtr = DESCRIPTOR_CAST(ConfigHeader, USB_Descriptor_Configuration_Header_t).TotalConfigurationSize;
-		#else
-		*ConfigSizePtr = DESCRIPTOR_CAST(ConfigHeader, USB_Descriptor_Configuration_Header_t).wTotalLength;		
-		#endif
-	}
-	else
-	{
-		USB_ControlRequest.wLength = *ConfigSizePtr;
-		
-		ErrorCode      = USB_Host_SendControlRequest(BufferPtr);				
-	}
+	if (*ConfigSizePtr > BufferSize)
+	  return HOST_GETCONFIG_BuffOverflow;
+	  
+	USB_ControlRequest.wLength = *ConfigSizePtr;
+	
+	if ((ErrorCode = USB_Host_SendControlRequest(BufferPtr)) != HOST_SENDCONTROL_Successful)
+	  return ErrorCode;
 
-	return ErrorCode;
+	if (DESCRIPTOR_TYPE(BufferPtr) != DTYPE_Configuration)
+	  return HOST_GETCONFIG_InvalidData;
+	
+	return HOST_GETCONFIG_Successful;
 }
 #endif
 
diff --git a/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.h b/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.h
index a9b0b1423..8c4e2c2db 100644
--- a/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.h
+++ b/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.h
@@ -163,6 +163,23 @@
 			uint8_t USB_GetNextDescriptorComp(uint16_t* BytesRem, uint8_t** CurrConfigLoc, ConfigComparatorPtr_t ComparatorRoutine);
 			
 		/* Enums: */
+			enum USB_Host_GetConfigDescriptor_ErrorCodes_t
+			{
+				HOST_GETCONFIG_Successful       = 0, /**< No error occurred while retrieving the configuration descriptor */
+				HOST_GETCONFIG_DeviceDisconnect = 1, /**< The attached device was disconnected while retrieving the configuration
+				                                        * descriptor
+				                                        */
+				HOST_GETCONFIG_PipeError        = 2, /**< An error occurred in the pipe while sending the request */
+				HOST_GETCONFIG_SetupStalled     = 3, /**< The attached device stalled the request to retrieve the configuration
+				                                        * descriptor
+				                                        */
+				HOST_GETCONFIG_SoftwareTimeOut  = 4, /**< The request or data transfer timed out */
+				HOST_GETCONFIG_BuffOverflow     = 5, /**< The device's configuration descriptor is too large to fit into the allocated
+				                                        * buffer
+				                                        */
+				HOST_GETCONFIG_InvalidData      = 6, /**< The device returned invalid configuration descriptor data */
+			};
+		
 			/** Enum for return values of a descriptor comparator function. */
 			enum DSearch_Return_ErrorCodes_t
 			{
@@ -181,22 +198,19 @@
 			};
 	
 		/* Function Prototypes: */
-			/** Retrieves the configuration descriptor data or size from an attached device via a standard request.
+			/** Retrieves the configuration descriptor data from an attached device via a standard request into a buffer,
+			 *  including validity and size checking to prevent a buffer overflow.
 			 *
 			 *  \param[in] ConfigNumber  Device configuration descriptor number to fetch from the device (usually set to 1 for
 			 *                           single configuration devices)
+			 *  \param[in,out] ConfigSizePtr  Pointer to a uint16_t for storing the retrieved configuration descriptor size
+			 *  \param[out] BufferPtr  Pointer to the buffer for storing the configuration descriptor data.
+			 *  \param[out] BufferSize  Size of the allocated buffer where the configuration descriptor is to be stored
 			 *
-			 *  \param[in,out] ConfigSizePtr  Pointer to a uint16_t for either storing or retrieving the configuration
-			 *                                descriptor size
-			 *
-			 *  \param[out] BufferPtr  Pointer to the buffer for storing the configuration descriptor data. If this is
-			 *                         NULL, the size of the configuration descriptor will be retrieved instead and
-			 *                         placed in the variable pointed to by ConfigSizePtr. If this is non-NULL, the number
-			 *                         of bytes indicated by ConfigSizePtr of the configuration descriptor will be loaded
-			 *                         into the buffer
+			 *  \return A value from the \ref USB_Host_GetConfigDescriptor_ErrorCodes_t enum
 			 */
-			uint8_t USB_GetDeviceConfigDescriptor(uint8_t ConfigNumber, uint16_t* const ConfigSizePtr, void* BufferPtr)
-			                                      ATTR_NON_NULL_PTR_ARG(2);
+			uint8_t USB_GetDeviceConfigDescriptor(uint8_t ConfigNumber, uint16_t* const ConfigSizePtr, void* BufferPtr,
+			                                      uint16_t BufferSize) ATTR_NON_NULL_PTR_ARG(2, 3);
 
 			/** Skips to the next sub-descriptor inside the configuration descriptor of the specified type value.
 			 *  The bytes remaining value is automatically decremented.
diff --git a/LUFA/ManPages/ChangeLog.txt b/LUFA/ManPages/ChangeLog.txt
index 8530f705f..1750bfaeb 100644
--- a/LUFA/ManPages/ChangeLog.txt
+++ b/LUFA/ManPages/ChangeLog.txt
@@ -29,6 +29,8 @@
   *  - Added new "Common" section to the class drivers, to hold all mode-independant definitions for clarity
   *  - Moved SCSI command/sense constants into the Mass Storage Class driver, instead of the user-code
   *  - Altered the SCSI commands in the LowLevel Mass Storage Host to save on FLASH space by reducing function calls
+  *  - Changed the parameters and behaviour of the USB_GetDeviceConfigDescriptor() function so that it now performs size checks
+  *    and data validations internally, to simplify user code
   *
   *  <b>Fixed:</b>
   *  - Fixed possible lockup in the CDC device class driver, when the host sends data that is a multiple of the
diff --git a/LUFA/ManPages/MigrationInformation.txt b/LUFA/ManPages/MigrationInformation.txt
index d83043182..9527a373c 100644
--- a/LUFA/ManPages/MigrationInformation.txt
+++ b/LUFA/ManPages/MigrationInformation.txt
@@ -19,6 +19,12 @@
  *    - The SPI_Init() routine's parameters have changed, so that the clock polarity and data sampling modes can be set. See
  *      the SPI_Init() function documentation for more details
  *
+ *  <b>Host Mode</b>
+ *    - The \ref USB_GetDeviceConfigDescriptor() function's parameters and behaviour has changed; the user is required to
+ *      preallocate the largest allowable buffer, and pass the size of the buffer to the function. This allows for a single
+ *      call to the function to retrieve, size check and validate the Configuration Descriptor rather than having the user
+ *      application perform these intermediatary steps.
+ *
  * \section Sec_Migration090810 Migrating from 090605 to 090810
  *
  *  <b>All</b>
-- 
GitLab