From 3d1baa6f953c3c78c78c31466c4f551123e84415 Mon Sep 17 00:00:00 2001
From: Dean Camera <dean@fourwalledcubicle.com>
Date: Fri, 5 Jun 2009 02:23:31 +0000
Subject: [PATCH] Added multiple Report ID support to the HID class driver.
 Removed OUT endpoint support from HID driver (all OUT reports are now
 processed through control requests) as a seperate endpoint had issues with
 determining the exact output report length.

---
 Demos/Device/GenericHID/Descriptors.c      | 12 +-----
 Demos/Device/GenericHID/Descriptors.h      |  4 --
 Demos/Device/GenericHID/GenericHID.c       |  8 ++--
 Demos/Device/GenericHID/GenericHID.h       |  4 +-
 Demos/Device/Joystick/Joystick.c           |  5 ++-
 Demos/Device/Joystick/Joystick.h           |  4 +-
 Demos/Device/Keyboard/Descriptors.c        | 12 +-----
 Demos/Device/Keyboard/Descriptors.h        |  4 --
 Demos/Device/Keyboard/Keyboard.c           |  8 ++--
 Demos/Device/Keyboard/Keyboard.h           |  4 +-
 Demos/Device/KeyboardMouse/Descriptors.c   | 12 +-----
 Demos/Device/KeyboardMouse/Descriptors.h   |  4 --
 Demos/Device/KeyboardMouse/KeyboardMouse.c | 11 ++----
 Demos/Device/KeyboardMouse/KeyboardMouse.h |  4 +-
 Demos/Device/Mouse/Mouse.c                 |  5 ++-
 Demos/Device/Mouse/Mouse.h                 |  4 +-
 LUFA/Drivers/USB/Class/Device/CDC.c        |  2 +-
 LUFA/Drivers/USB/Class/Device/CDC.h        | 30 +++++++++++----
 LUFA/Drivers/USB/Class/Device/HID.c        | 45 +++++++---------------
 LUFA/Drivers/USB/Class/Device/HID.h        | 29 +++++++++++---
 LUFA/Drivers/USB/Class/Device/MIDI.h       |  2 +-
 Projects/Magstripe/Magstripe.c             |  5 ++-
 Projects/Magstripe/Magstripe.h             |  6 +--
 23 files changed, 96 insertions(+), 128 deletions(-)

diff --git a/Demos/Device/GenericHID/Descriptors.c b/Demos/Device/GenericHID/Descriptors.c
index ca1a110e7c..6988166b31 100644
--- a/Demos/Device/GenericHID/Descriptors.c
+++ b/Demos/Device/GenericHID/Descriptors.c
@@ -119,7 +119,7 @@ USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
 			.InterfaceNumber        = 0x00,
 			.AlternateSetting       = 0x00,
 			
-			.TotalEndpoints         = 2,
+			.TotalEndpoints         = 1,
 				
 			.Class                  = 0x03,
 			.SubClass               = 0x00,
@@ -148,16 +148,6 @@ USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
 			.EndpointSize           = GENERIC_EPSIZE,
 			.PollingIntervalMS      = 0x02
 		},
-
-	.GenericOUTEndpoint = 
-		{
-			.Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
-										 
-			.EndpointAddress        = (ENDPOINT_DESCRIPTOR_DIR_OUT | GENERIC_OUT_EPNUM),
-			.Attributes             = EP_TYPE_INTERRUPT,
-			.EndpointSize           = GENERIC_EPSIZE,
-			.PollingIntervalMS      = 0x02
-		}
 };
 
 /** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests
diff --git a/Demos/Device/GenericHID/Descriptors.h b/Demos/Device/GenericHID/Descriptors.h
index bc4c68ae6b..01db53e410 100644
--- a/Demos/Device/GenericHID/Descriptors.h
+++ b/Demos/Device/GenericHID/Descriptors.h
@@ -53,16 +53,12 @@
 			USB_Descriptor_Interface_t            Interface;
 			USB_Descriptor_HID_t                  GenericHID;
 	        USB_Descriptor_Endpoint_t             GenericINEndpoint;
-	        USB_Descriptor_Endpoint_t             GenericOUTEndpoint;
 		} USB_Descriptor_Configuration_t;
 
 	/* Macros: */
 		/** Endpoint number of the Generic HID reporting IN endpoint. */
 		#define GENERIC_IN_EPNUM          1
 
-		/** Endpoint number of the Generic HID reporting OUT endpoint. */
-		#define GENERIC_OUT_EPNUM         2
-
 		/** Size in bytes of the Generic HID reporting endpoint. */
 		#define GENERIC_EPSIZE            8
 		
diff --git a/Demos/Device/GenericHID/GenericHID.c b/Demos/Device/GenericHID/GenericHID.c
index b933e4506b..172df7fa71 100644
--- a/Demos/Device/GenericHID/GenericHID.c
+++ b/Demos/Device/GenericHID/GenericHID.c
@@ -47,9 +47,6 @@ USB_ClassInfo_HID_t Generic_HID_Interface =
 		.ReportINEndpointNumber  = GENERIC_IN_EPNUM,
 		.ReportINEndpointSize    = GENERIC_EPSIZE,
 		
-		.ReportOUTEndpointNumber = GENERIC_OUT_EPNUM,
-		.ReportOUTEndpointSize   = GENERIC_EPSIZE,
-		
 		.ReportINBufferSize      = GENERIC_REPORT_SIZE,
 
 		.UsingReportProtocol     = true,
@@ -133,7 +130,7 @@ ISR(TIMER0_COMPA_vect, ISR_BLOCK)
  *
  *  \return Number of bytes written in the report (or zero if no report is to be sent
  */
-uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData)
+uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t* ReportID, void* ReportData)
 {
 	// Create generic HID report here
 	
@@ -146,7 +143,8 @@ uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceI
  *  \param ReportData  Pointer to a buffer where the created report has been stored
  *  \param ReportSize  Size in bytes of the received HID report
  */
-void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData, uint16_t ReportSize)
+void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t ReportID,
+                                               void* ReportData, uint16_t ReportSize)
 {
 	// Process received generic HID report here
 }
diff --git a/Demos/Device/GenericHID/GenericHID.h b/Demos/Device/GenericHID/GenericHID.h
index b68dc4c24c..5ea084c7e5 100644
--- a/Demos/Device/GenericHID/GenericHID.h
+++ b/Demos/Device/GenericHID/GenericHID.h
@@ -72,8 +72,8 @@
 		void EVENT_USB_ConfigurationChanged(void);
 		void EVENT_USB_UnhandledControlPacket(void);
 
-		uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData);
-		void     CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo,
+		uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t* ReportID, void* ReportData);
+		void     CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t ReportID, 
 		                                                   void* ReportData, uint16_t ReportSize);
 		
 #endif
diff --git a/Demos/Device/Joystick/Joystick.c b/Demos/Device/Joystick/Joystick.c
index 66cb808d0f..1cf59bbfd4 100644
--- a/Demos/Device/Joystick/Joystick.c
+++ b/Demos/Device/Joystick/Joystick.c
@@ -132,7 +132,7 @@ ISR(TIMER0_COMPA_vect, ISR_BLOCK)
  *
  *  \return Number of bytes written in the report (or zero if no report is to be sent
  */
-uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData)
+uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t* ReportID, void* ReportData)
 {
 	USB_JoystickReport_Data_t* JoystickReport = (USB_JoystickReport_Data_t*)ReportData;
 	
@@ -164,7 +164,8 @@ uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceI
  *  \param ReportData  Pointer to a buffer where the created report has been stored
  *  \param ReportSize  Size in bytes of the received HID report
  */
-void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData, uint16_t ReportSize)
+void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t ReportID,
+                                               void* ReportData, uint16_t ReportSize)
 {
 	// Unused (but mandatory for the HID class driver) in this demo, since there are no Host->Device reports
 }
diff --git a/Demos/Device/Joystick/Joystick.h b/Demos/Device/Joystick/Joystick.h
index 9db357b403..4209f4d7ed 100644
--- a/Demos/Device/Joystick/Joystick.h
+++ b/Demos/Device/Joystick/Joystick.h
@@ -83,8 +83,8 @@
 		void EVENT_USB_ConfigurationChanged(void);
 		void EVENT_USB_UnhandledControlPacket(void);
 
-		uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData);
-		void     CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo,
+		uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t* ReportID, void* ReportData);
+		void     CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t ReportID, 
 		                                                   void* ReportData, uint16_t ReportSize);
 
 #endif
diff --git a/Demos/Device/Keyboard/Descriptors.c b/Demos/Device/Keyboard/Descriptors.c
index ddd19fc8cf..8914909d77 100644
--- a/Demos/Device/Keyboard/Descriptors.c
+++ b/Demos/Device/Keyboard/Descriptors.c
@@ -136,7 +136,7 @@ USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
 			.InterfaceNumber        = 0x00,
 			.AlternateSetting       = 0x00,
 			
-			.TotalEndpoints         = 2,
+			.TotalEndpoints         = 1,
 				
 			.Class                  = 0x03,
 			.SubClass               = 0x01,
@@ -165,16 +165,6 @@ USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
 			.EndpointSize           = KEYBOARD_EPSIZE,
 			.PollingIntervalMS      = 0x04
 		},
-
-	.KeyboardLEDsEndpoint = 
-		{
-			.Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
-
-			.EndpointAddress        = (ENDPOINT_DESCRIPTOR_DIR_OUT | KEYBOARD_LEDS_EPNUM),
-			.Attributes             = EP_TYPE_INTERRUPT,
-			.EndpointSize           = KEYBOARD_EPSIZE,
-			.PollingIntervalMS      = 0x04
-		}
 };
 
 /** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests
diff --git a/Demos/Device/Keyboard/Descriptors.h b/Demos/Device/Keyboard/Descriptors.h
index 0a95ca06e8..40b358caa0 100644
--- a/Demos/Device/Keyboard/Descriptors.h
+++ b/Demos/Device/Keyboard/Descriptors.h
@@ -54,15 +54,11 @@
 			USB_Descriptor_Interface_t            Interface;
 			USB_Descriptor_HID_t                  KeyboardHID;
 	        USB_Descriptor_Endpoint_t             KeyboardEndpoint;
-	        USB_Descriptor_Endpoint_t             KeyboardLEDsEndpoint;
 		} USB_Descriptor_Configuration_t;
 					
 	/* Macros: */
 		/** Endpoint number of the Keyboard HID reporting IN endpoint. */
 		#define KEYBOARD_EPNUM               1
-
-		/** Endpoint number of the Keyboard HID reporting OUT endpoint. */
-		#define KEYBOARD_LEDS_EPNUM          2
 		
 		/** Size in bytes of the Keyboard HID reporting IN and OUT endpoints. */		
 		#define KEYBOARD_EPSIZE              8
diff --git a/Demos/Device/Keyboard/Keyboard.c b/Demos/Device/Keyboard/Keyboard.c
index 923dd71769..bebad12e03 100644
--- a/Demos/Device/Keyboard/Keyboard.c
+++ b/Demos/Device/Keyboard/Keyboard.c
@@ -48,9 +48,6 @@ USB_ClassInfo_HID_t Keyboard_HID_Interface =
         .ReportINEndpointNumber  = KEYBOARD_EPNUM,
         .ReportINEndpointSize    = KEYBOARD_EPSIZE,
 
-        .ReportOUTEndpointNumber = KEYBOARD_LEDS_EPNUM,
-        .ReportOUTEndpointSize   = KEYBOARD_EPSIZE,
-        
 		.ReportINBufferSize      = sizeof(USB_KeyboardReport_Data_t),
 
         .IdleCount               = 500,
@@ -136,7 +133,7 @@ ISR(TIMER0_COMPA_vect, ISR_BLOCK)
  *
  *  \return Number of bytes written in the report (or zero if no report is to be sent
  */
-uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData)
+uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t* ReportID, void* ReportData)
 {
     USB_KeyboardReport_Data_t* KeyboardReport = (USB_KeyboardReport_Data_t*)ReportData;
     
@@ -168,7 +165,8 @@ uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceI
  *  \param ReportData  Pointer to a buffer where the created report has been stored
  *  \param ReportSize  Size in bytes of the received HID report
  */
-void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData, uint16_t ReportSize)
+void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t ReportID,
+                                               void* ReportData, uint16_t ReportSize)
 {
     uint8_t  LEDMask   = LEDS_NO_LEDS;
     uint8_t* LEDReport = (uint8_t*)ReportData;
diff --git a/Demos/Device/Keyboard/Keyboard.h b/Demos/Device/Keyboard/Keyboard.h
index e04ae9e340..1b4bb7092a 100644
--- a/Demos/Device/Keyboard/Keyboard.h
+++ b/Demos/Device/Keyboard/Keyboard.h
@@ -86,8 +86,8 @@
 		void EVENT_USB_ConfigurationChanged(void);
 		void EVENT_USB_UnhandledControlPacket(void);
 
-		uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData);
-		void     CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo,
+		uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t* ReportID, void* ReportData);
+		void     CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t ReportID, 
 		                                                   void* ReportData, uint16_t ReportSize);
 
 #endif
diff --git a/Demos/Device/KeyboardMouse/Descriptors.c b/Demos/Device/KeyboardMouse/Descriptors.c
index 145708db93..c9a778feb2 100644
--- a/Demos/Device/KeyboardMouse/Descriptors.c
+++ b/Demos/Device/KeyboardMouse/Descriptors.c
@@ -169,7 +169,7 @@ USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
 			.InterfaceNumber        = 0x00,
 			.AlternateSetting       = 0x00,
 			
-			.TotalEndpoints         = 2,
+			.TotalEndpoints         = 1,
 				
 			.Class                  = 0x03,
 			.SubClass               = 0x01,
@@ -199,16 +199,6 @@ USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
 			.PollingIntervalMS      = 0x02
 		},
 
-	.KeyboardOutEndpoint = 
-		{
-			.Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
-
-			.EndpointAddress        = (ENDPOINT_DESCRIPTOR_DIR_OUT | KEYBOARD_OUT_EPNUM),
-			.Attributes             = EP_TYPE_INTERRUPT,
-			.EndpointSize           = HID_EPSIZE,
-			.PollingIntervalMS      = 0x02
-		},
-
 	.MouseInterface = 
 		{
 			.Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
diff --git a/Demos/Device/KeyboardMouse/Descriptors.h b/Demos/Device/KeyboardMouse/Descriptors.h
index 152e5111af..1dcad086e2 100644
--- a/Demos/Device/KeyboardMouse/Descriptors.h
+++ b/Demos/Device/KeyboardMouse/Descriptors.h
@@ -54,7 +54,6 @@
 			USB_Descriptor_Interface_t            KeyboardInterface;
 			USB_Descriptor_HID_t                  KeyboardHID;
 	        USB_Descriptor_Endpoint_t             KeyboardInEndpoint;
-	        USB_Descriptor_Endpoint_t             KeyboardOutEndpoint;
 			USB_Descriptor_Interface_t            MouseInterface;
 			USB_Descriptor_HID_t                  MouseHID;
 	        USB_Descriptor_Endpoint_t             MouseInEndpoint;
@@ -64,9 +63,6 @@
 		/** Endpoint number of the Keyboard HID reporting IN endpoint. */
 		#define KEYBOARD_IN_EPNUM         1
 
-		/** Endpoint number of the Keyboard HID reporting OUT endpoint. */
-		#define KEYBOARD_OUT_EPNUM        2
-
 		/** Endpoint number of the Mouse HID reporting IN endpoint. */
 		#define MOUSE_IN_EPNUM            3
 
diff --git a/Demos/Device/KeyboardMouse/KeyboardMouse.c b/Demos/Device/KeyboardMouse/KeyboardMouse.c
index e68a247938..5cea555809 100644
--- a/Demos/Device/KeyboardMouse/KeyboardMouse.c
+++ b/Demos/Device/KeyboardMouse/KeyboardMouse.c
@@ -48,9 +48,6 @@ USB_ClassInfo_HID_t Keyboard_HID_Interface =
 
 		.ReportINEndpointNumber  = KEYBOARD_IN_EPNUM,
 		.ReportINEndpointSize    = HID_EPSIZE,
-
-		.ReportOUTEndpointNumber = KEYBOARD_OUT_EPNUM,
-		.ReportOUTEndpointSize   = HID_EPSIZE,
 		
 		.ReportINBufferSize      = sizeof(USB_KeyboardReport_Data_t),
 
@@ -70,9 +67,6 @@ USB_ClassInfo_HID_t Mouse_HID_Interface =
 		.ReportINEndpointSize    = HID_EPSIZE,
 
 		.ReportINBufferSize      = sizeof(USB_MouseReport_Data_t),
-
-		.ReportOUTEndpointNumber = 0,
-		.ReportOUTEndpointSize   = 0,
 	};
 
 /** Main program entry point. This routine contains the overall program flow, including initial
@@ -162,7 +156,7 @@ ISR(TIMER0_COMPA_vect, ISR_BLOCK)
  *
  *  \return Number of bytes written in the report (or zero if no report is to be sent
  */
-uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData)
+uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t* ReportID, void* ReportData)
 {
 	uint8_t JoyStatus_LCL    = Joystick_GetStatus();
 	uint8_t ButtonStatus_LCL = Buttons_GetStatus();
@@ -221,7 +215,8 @@ uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceI
  *  \param ReportData  Pointer to a buffer where the created report has been stored
  *  \param ReportSize  Size in bytes of the received HID report
  */
-void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData, uint16_t ReportSize)
+void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t ReportID,
+                                               void* ReportData, uint16_t ReportSize)
 {
 	if (HIDInterfaceInfo == &Keyboard_HID_Interface)
 	{
diff --git a/Demos/Device/KeyboardMouse/KeyboardMouse.h b/Demos/Device/KeyboardMouse/KeyboardMouse.h
index 9afe7646bc..74b1c9e5f2 100644
--- a/Demos/Device/KeyboardMouse/KeyboardMouse.h
+++ b/Demos/Device/KeyboardMouse/KeyboardMouse.h
@@ -90,8 +90,8 @@
 		void EVENT_USB_ConfigurationChanged(void);
 		void EVENT_USB_UnhandledControlPacket(void);
 
-		uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData);
-		void     CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo,
+		uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t* ReportID, void* ReportData);
+		void     CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t ReportID, 
 		                                                   void* ReportData, uint16_t ReportSize);
 		
 #endif
diff --git a/Demos/Device/Mouse/Mouse.c b/Demos/Device/Mouse/Mouse.c
index 1bc62dac69..f5bd931d17 100644
--- a/Demos/Device/Mouse/Mouse.c
+++ b/Demos/Device/Mouse/Mouse.c
@@ -130,7 +130,7 @@ ISR(TIMER0_COMPA_vect, ISR_BLOCK)
  *
  *  \return Number of bytes written in the report (or zero if no report is to be sent
  */
-uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData)
+uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t* ReportID, void* ReportData)
 {
 	USB_MouseReport_Data_t* MouseReport = (USB_MouseReport_Data_t*)ReportData;
 		
@@ -162,7 +162,8 @@ uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceI
  *  \param ReportData  Pointer to a buffer where the created report has been stored
  *  \param ReportSize  Size in bytes of the received HID report
  */
-void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData, uint16_t ReportSize)
+void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t ReportID,
+                                               void* ReportData, uint16_t ReportSize)
 {
 	// Unused (but mandatory for the HID class driver) in this demo, since there are no Host->Device reports
 }
diff --git a/Demos/Device/Mouse/Mouse.h b/Demos/Device/Mouse/Mouse.h
index 62d6d83236..6de20ee797 100644
--- a/Demos/Device/Mouse/Mouse.h
+++ b/Demos/Device/Mouse/Mouse.h
@@ -85,8 +85,8 @@
 		void EVENT_USB_ConfigurationChanged(void);
 		void EVENT_USB_UnhandledControlPacket(void);
 
-		uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData);
-		void     CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo,
+		uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t* ReportID, void* ReportData);
+		void     CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t ReportID, 
 		                                                   void* ReportData, uint16_t ReportSize);
 
 #endif
diff --git a/LUFA/Drivers/USB/Class/Device/CDC.c b/LUFA/Drivers/USB/Class/Device/CDC.c
index d27b0d2edc..dface2a6db 100644
--- a/LUFA/Drivers/USB/Class/Device/CDC.c
+++ b/LUFA/Drivers/USB/Class/Device/CDC.c
@@ -169,7 +169,7 @@ uint8_t USB_CDC_ReceiveByte(USB_ClassInfo_CDC_t* CDCInterfaceInfo)
 	return DataByte;
 }
 
-void USB_CDC_SendSerialLineStateChanged(USB_ClassInfo_CDC_t* CDCInterfaceInfo, uint16_t LineStateMask)
+void USB_CDC_SendSerialLineStateChange(USB_ClassInfo_CDC_t* CDCInterfaceInfo, uint16_t LineStateMask)
 {
 	Endpoint_SelectEndpoint(CDCInterfaceInfo->NotificationEndpointNumber);
 	
diff --git a/LUFA/Drivers/USB/Class/Device/CDC.h b/LUFA/Drivers/USB/Class/Device/CDC.h
index 3e67b1b6b6..ee9e3767db 100644
--- a/LUFA/Drivers/USB/Class/Device/CDC.h
+++ b/LUFA/Drivers/USB/Class/Device/CDC.h
@@ -167,7 +167,7 @@
 			uint8_t  NotificationEndpointNumber; /**< Endpoint number of the CDC interface's IN notification endpoint, if used */
 			uint16_t NotificationEndpointSize;  /**< Size in bytes of the CDC interface's IN notification endpoint, if used */
 
-			uint8_t  ControlLineState; /**< Current control line state, as set by the host */
+			uint8_t  ControlLineState; /**< Current control line states, as set by the host */
 
 			struct
 			{
@@ -195,7 +195,7 @@
 		 *  \ref EVENT_USB_ConfigurationChanged() event so that the endpoints are configured when the configuration containing the
 		 *  given CDC interface is selected.
 		 *
-		 *  \param CDCInterfaceInfo  Pointer to a structure containing an CDC Class configuration and state.
+		 *  \param CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state.
 		 *
 		 *  \return Boolean true if the endpoints were sucessfully configured, false otherwise
 		 */
@@ -204,25 +204,41 @@
 		/** Processes incomming control requests from the host, that are directed to the given CDC class interface. This should be
 		 *  linked to the library \ref EVENT_USB_UnhandledControlPacket() event.
 		 *
-		 *  \param CDCInterfaceInfo  Pointer to a structure containing an CDC Class configuration and state.
+		 *  \param CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state.
 		 */
 		void USB_CDC_ProcessControlPacket(USB_ClassInfo_CDC_t* CDCInterfaceInfo);
 
 		/** General management task for a given CDC class interface, required for the correct operation of the interface. This should
 		 *  be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
 		 *
-		 *  \param CDCInterfaceInfo  Pointer to a structure containing an CDC Class configuration and state.
+		 *  \param CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state.
 		 */
 		void USB_CDC_USBTask(USB_ClassInfo_CDC_t* CDCInterfaceInfo);
 
-		void     EVENT_USB_CDC_LineEncodingChanged(USB_ClassInfo_CDC_t* CDCInterfaceInfo);
-		void     EVENT_USB_CDC_ControLineStateChanged(USB_ClassInfo_CDC_t* CDCInterfaceInfo);
+		/** CDC class driver event for a line encoding change on a CDC interface. This event fires each time the host requests a
+		 *  line encoding change (containing the serial parity, baud and other configuration information) and may be hooked in the
+		 *  user program by declaring a handler function with the same name and parameters listed here. The new line encoding
+		 *  settings are available in the LineEncoding structure inside the CDC interface structure passed as a parameter.
+		 *
+		 *  \param CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state.
+		 */
+		void EVENT_USB_CDC_LineEncodingChanged(USB_ClassInfo_CDC_t* CDCInterfaceInfo);
+		
+		/** CDC class driver event for a control line state change on a CDC interface. This event fires each time the host requests a
+		 *  control line state change (containing the virtual serial control line states, such as DTR) and may be hooked in the
+		 *  user program by declaring a handler function with the same name and parameters listed here. The new control line states
+		 *  are available in the ControlLineState value inside the CDC interface structure passed as a parameter, set as a mask of
+		 *  CDC_CONTROL_LINE_OUT_* masks.
+		 *
+		 *  \param CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state.
+		 */		
+		void EVENT_USB_CDC_ControLineStateChanged(USB_ClassInfo_CDC_t* CDCInterfaceInfo);
 
 		void     USB_CDC_SendString(USB_ClassInfo_CDC_t* CDCInterfaceInfo, char* Data, uint16_t Length);
 		void     USB_CDC_SendByte(USB_ClassInfo_CDC_t* CDCInterfaceInfo, uint8_t Data);
 		uint16_t USB_CDC_BytesReceived(USB_ClassInfo_CDC_t* CDCInterfaceInfo);
 		uint8_t  USB_CDC_ReceiveByte(USB_ClassInfo_CDC_t* CDCInterfaceInfo);
-		void USB_CDC_SendSerialLineStateChanged(USB_ClassInfo_CDC_t* CDCInterfaceInfo, uint16_t LineStateMask);
+		void     USB_CDC_SendSerialLineStateChange(USB_ClassInfo_CDC_t* CDCInterfaceInfo, uint16_t LineStateMask);
 
 	/* Disable C linkage for C++ Compilers: */
 		#if defined(__cplusplus)
diff --git a/LUFA/Drivers/USB/Class/Device/HID.c b/LUFA/Drivers/USB/Class/Device/HID.c
index 5f8ccfbaef..06992189f3 100644
--- a/LUFA/Drivers/USB/Class/Device/HID.c
+++ b/LUFA/Drivers/USB/Class/Device/HID.c
@@ -47,10 +47,11 @@ void USB_HID_ProcessControlPacket(USB_ClassInfo_HID_t* HIDInterfaceInfo)
 
 				uint8_t  ReportINData[HIDInterfaceInfo->ReportINBufferSize];
 				uint16_t ReportINSize;
+				uint8_t  ReportID = (USB_ControlRequest.wValue & 0xFF);
 
 				memset(ReportINData, 0, sizeof(ReportINData));
-
-				ReportINSize = CALLBACK_USB_HID_CreateNextHIDReport(HIDInterfaceInfo, ReportINData);
+				
+				ReportINSize = CALLBACK_USB_HID_CreateNextHIDReport(HIDInterfaceInfo, &ReportID, ReportINData);
 
 				Endpoint_Write_Control_Stream_LE(ReportINData, ReportINSize);
 				Endpoint_ClearOUT();
@@ -64,11 +65,12 @@ void USB_HID_ProcessControlPacket(USB_ClassInfo_HID_t* HIDInterfaceInfo)
 				
 				uint16_t ReportOUTSize = USB_ControlRequest.wLength;
 				uint8_t  ReportOUTData[ReportOUTSize];
+				uint8_t  ReportID = (USB_ControlRequest.wValue & 0xFF);
 
 				Endpoint_Read_Control_Stream_LE(ReportOUTData, ReportOUTSize);
 				Endpoint_ClearIN();
 				
-				CALLBACK_USB_HID_ProcessReceivedHIDReport(HIDInterfaceInfo, ReportOUTData, ReportOUTSize);
+				CALLBACK_USB_HID_ProcessReceivedHIDReport(HIDInterfaceInfo, ReportID, ReportOUTData, ReportOUTSize);
 			}
 			
 			break;
@@ -135,15 +137,6 @@ bool USB_HID_ConfigureEndpoints(USB_ClassInfo_HID_t* HIDInterfaceInfo)
 		return false;
 	}
 	
-	if (HIDInterfaceInfo->ReportOUTEndpointNumber)
-	{
-		if (!(Endpoint_ConfigureEndpoint(HIDInterfaceInfo->ReportOUTEndpointNumber, EP_TYPE_INTERRUPT,
-										 ENDPOINT_DIR_OUT, HIDInterfaceInfo->ReportOUTEndpointSize, ENDPOINT_BANK_SINGLE)))
-		{
-			return false;
-		}
-	}
-	
 	return true;
 }
 		
@@ -162,32 +155,20 @@ void USB_HID_USBTask(USB_ClassInfo_HID_t* HIDInterfaceInfo)
 
 		uint8_t  ReportINData[HIDInterfaceInfo->ReportINBufferSize];
 		uint16_t ReportINSize;
+		uint8_t  ReportID = 0;
 
 		memset(ReportINData, 0, sizeof(ReportINData));
 
-		ReportINSize = CALLBACK_USB_HID_CreateNextHIDReport(HIDInterfaceInfo, ReportINData);
+		ReportINSize = CALLBACK_USB_HID_CreateNextHIDReport(HIDInterfaceInfo, &ReportID, ReportINData);
 
 		if (ReportINSize)
-		  Endpoint_Write_Stream_LE(ReportINData, ReportINSize, NO_STREAM_CALLBACK);
+		{
+			if (ReportID)
+			  Endpoint_Write_Stream_LE(&ReportID, sizeof(ReportID), NO_STREAM_CALLBACK);
+
+			Endpoint_Write_Stream_LE(ReportINData, ReportINSize, NO_STREAM_CALLBACK);
+		}
 		
 		Endpoint_ClearIN();
 	}
-	
-	if (HIDInterfaceInfo->ReportOUTEndpointNumber)
-	{
-		Endpoint_SelectEndpoint(HIDInterfaceInfo->ReportOUTEndpointNumber);
-		
-		if (Endpoint_IsOUTReceived())
-		{
-			uint16_t ReportOUTSize = Endpoint_BytesInEndpoint();
-			uint8_t  ReportOUTData[ReportOUTSize];
-			
-			if (ReportOUTSize)
-			  Endpoint_Read_Stream_LE(ReportOUTData, ReportOUTSize, NO_STREAM_CALLBACK);
-			  
-			CALLBACK_USB_HID_ProcessReceivedHIDReport(HIDInterfaceInfo, ReportOUTData, ReportOUTSize);
-			
-			Endpoint_ClearOUT();
-		}
-	}
 }
diff --git a/LUFA/Drivers/USB/Class/Device/HID.h b/LUFA/Drivers/USB/Class/Device/HID.h
index 9a563040c0..4fd6f2c22b 100644
--- a/LUFA/Drivers/USB/Class/Device/HID.h
+++ b/LUFA/Drivers/USB/Class/Device/HID.h
@@ -111,9 +111,6 @@
 
 			uint8_t  ReportINEndpointNumber; /**< Endpoint number of the HID interface's IN report endpoint */
 			uint16_t ReportINEndpointSize; /**< Size in bytes of the HID interface's IN report endpoint */
-
-			uint8_t  ReportOUTEndpointNumber; /**< Endpoint number of the HID interface's OUT report endpoint, if used */
-			uint16_t ReportOUTEndpointSize;  /**< Size in bytes of the HID interface's OUT report endpoint, if used */
 			
 			uint8_t  ReportINBufferSize;
 
@@ -127,8 +124,30 @@
 		void USB_HID_ProcessControlPacket(USB_ClassInfo_HID_t* HIDInterfaceInfo);
 		void USB_HID_USBTask(USB_ClassInfo_HID_t* HIDInterfaceInfo);
 		
-		uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData);
-		void     CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData, uint16_t ReportSize);
+		/** HID class driver callback for the user creation of a HID input report. This callback may fire in response to either
+		 *  HID class control requests from the host, or by the normal HID endpoint polling procedure. Inside this callback the
+		 *  user is responsible for the creation of the next HID input report to be sent to the host.
+		 *
+		 *  \param HIDInterfaceInfo  Pointer to a structure containing a HID Class configuration and state.
+		 *  \param ReportID  If preset to a non-zero value, this is the report ID being requested by the host. If zero, this should
+		 *                   be set to the report ID of the generated HID input report. If multiple reports are not sent via the
+		 *                   given HID interface, this parameter should be ignored.
+		 *  \param ReportData  Pointer to a buffer where the generated HID report should be stored.
+		 *
+		 *  \return  Number of bytes in the generated input report, or zero if no report is to be sent
+		 */
+		uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t* ReportID, void* ReportData);
+
+		/** HID class driver callback for the user processing of a received HID input report. This callback may fire in response to
+		 *  either HID class control requests from the host, or by the normal HID endpoint polling procedure. Inside this callback
+		 *  the user is responsible for the processing of the received HID output report from the host.
+		 *
+		 *  \param HIDInterfaceInfo  Pointer to a structure containing a HID Class configuration and state.
+		 *  \param ReportID  Report ID of the received output report. If multiple reports are not received via the given HID
+		 *                   interface, this parameter should be ignored.
+		 *  \param ReportData  Pointer to a buffer where the received HID report is stored.
+		 */
+		void     CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t ReportID, void* ReportData, uint16_t ReportSize);
 
 	/* Disable C linkage for C++ Compilers: */
 		#if defined(__cplusplus)
diff --git a/LUFA/Drivers/USB/Class/Device/MIDI.h b/LUFA/Drivers/USB/Class/Device/MIDI.h
index b2294d86c5..08a530af2e 100644
--- a/LUFA/Drivers/USB/Class/Device/MIDI.h
+++ b/LUFA/Drivers/USB/Class/Device/MIDI.h
@@ -76,7 +76,7 @@
 		/** MIDI command for a note off (deactivation) event */
 		#define MIDI_COMMAND_NOTE_OFF       0x08
 
-		/** Standard key press velocity value used for all note events, as no pressure sensor is mounted */
+		/** Standard key press velocity value used for all note events */
 		#define MIDI_STANDARD_VELOCITY      64
 		
 		/** Convenience macro. MIDI channels are numbered from 1-10 (natural numbers) however the logical channel
diff --git a/Projects/Magstripe/Magstripe.c b/Projects/Magstripe/Magstripe.c
index e32397c8bb..6e5e00b910 100644
--- a/Projects/Magstripe/Magstripe.c
+++ b/Projects/Magstripe/Magstripe.c
@@ -157,7 +157,7 @@ ISR(TIMER0_COMPA_vect, ISR_BLOCK)
  *
  *  \return Number of bytes in the created report
  */
-uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData)
+uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t* ReportID, void* ReportData)
 {
 	static bool IsKeyReleaseReport;
 	static bool IsNewlineReport;
@@ -204,7 +204,8 @@ uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceI
  *  \param ReportData  Pointer to the report buffer where the received report is stored
  *  \param ReportSize  Size in bytes of the report received from the host
  */
-void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData, uint16_t ReportSize)
+void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t ReportID,
+                                               void* ReportData, uint16_t ReportSize)
 {
 	// Unused (but mandatory for the HID class driver) in this demo, since there are no Host->Device reports
 }
diff --git a/Projects/Magstripe/Magstripe.h b/Projects/Magstripe/Magstripe.h
index 2b8aa3770d..6a13af4ec5 100644
--- a/Projects/Magstripe/Magstripe.h
+++ b/Projects/Magstripe/Magstripe.h
@@ -79,8 +79,8 @@
 		void EVENT_USB_ConfigurationChanged(void);
 		void EVENT_USB_UnhandledControlPacket(void);
 
-		uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData);
-		void     CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo,
-		                                                   void* ReportData, uint16_t ReportSize);
+		uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t* ReportID, void* ReportData);
+		void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, uint8_t ReportID,
+                                                       void* ReportData, uint16_t ReportSize);
 		
 #endif