summary refs log tree commit diff
diff options
context:
space:
mode:
authortmk <nobody@nowhere>2012-06-27 18:31:33 +0900
committertmk <nobody@nowhere>2012-06-27 18:31:33 +0900
commit3969ec09b48026b51e9d7c210b7c8d15dceb3b4b (patch)
tree113e48a9c772fed881e86168265110a485f23f36
parentdd93d2915f79d0b825fc6bbc4edb556a69eac406 (diff)
Add sendchar with Generic HID to support debug print.
-rw-r--r--keyboard/lufa/Descriptors.c791
-rw-r--r--keyboard/lufa/Descriptors.h89
-rw-r--r--keyboard/lufa/Makefile3
-rw-r--r--keyboard/lufa/lufa.c129
-rw-r--r--keyboard/lufa/lufa.h2
5 files changed, 595 insertions, 419 deletions
diff --git a/keyboard/lufa/Descriptors.c b/keyboard/lufa/Descriptors.c
index 3195aa77a6..a4e9defab4 100644
--- a/keyboard/lufa/Descriptors.c
+++ b/keyboard/lufa/Descriptors.c
@@ -1,359 +1,432 @@
-/*

-             LUFA Library

-     Copyright (C) Dean Camera, 2012.

-

-  dean [at] fourwalledcubicle [dot] com

-           www.lufa-lib.org

-*/

-

-/*

-  Copyright 2012  Dean Camera (dean [at] fourwalledcubicle [dot] com)

-  Copyright 2010  Denver Gingerich (denver [at] ossguy [dot] com)

-

-  Permission to use, copy, modify, distribute, and sell this

-  software and its documentation for any purpose is hereby granted

-  without fee, provided that the above copyright notice appear in

-  all copies and that both that the copyright notice and this

-  permission notice and warranty disclaimer appear in supporting

-  documentation, and that the name of the author not be used in

-  advertising or publicity pertaining to distribution of the

-  software without specific, written prior permission.

-

-  The author disclaim all warranties with regard to this

-  software, including all implied warranties of merchantability

-  and fitness.  In no event shall the author be liable for any

-  special, indirect or consequential damages or any damages

-  whatsoever resulting from loss of use, data or profits, whether

-  in an action of contract, negligence or other tortious action,

-  arising out of or in connection with the use or performance of

-  this software.

-*/

-

-/** \file

- *

- *  USB Device Descriptors, for library use when in USB device mode. Descriptors are special

- *  computer-readable structures which the host requests upon device enumeration, to determine

- *  the device's capabilities and functions.

- */

-

-#include "Descriptors.h"

-

-/** HID class report descriptor. This is a special descriptor constructed with values from the

- *  USBIF HID class specification to describe the reports and capabilities of the HID device. This

- *  descriptor is parsed by the host and its contents used to determine what data (and in what encoding)

- *  the device will send, and what it may be sent back from the host. Refer to the HID specification for

- *  more details on HID report descriptors.

- *

- *  This descriptor describes the mouse HID interface's report structure.

- */

-const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] =

-{

-	HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */

-	HID_RI_USAGE(8, 0x02), /* Mouse */

-	HID_RI_COLLECTION(8, 0x01), /* Application */

-	    HID_RI_USAGE(8, 0x01), /* Pointer */

-	    HID_RI_COLLECTION(8, 0x00), /* Physical */

-	        HID_RI_USAGE_PAGE(8, 0x09), /* Button */

-	        HID_RI_USAGE_MINIMUM(8, 0x01),

-	        HID_RI_USAGE_MAXIMUM(8, 0x03),

-	        HID_RI_LOGICAL_MINIMUM(8, 0x00),

-	        HID_RI_LOGICAL_MAXIMUM(8, 0x01),

-	        HID_RI_REPORT_COUNT(8, 0x03),

-	        HID_RI_REPORT_SIZE(8, 0x01),

-	        HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),

-	        HID_RI_REPORT_COUNT(8, 0x01),

-	        HID_RI_REPORT_SIZE(8, 0x05),

-	        HID_RI_INPUT(8, HID_IOF_CONSTANT),

-	        HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */

-	        HID_RI_USAGE(8, 0x30), /* Usage X */

-	        HID_RI_USAGE(8, 0x31), /* Usage Y */

-	        HID_RI_LOGICAL_MINIMUM(8, -1),

-	        HID_RI_LOGICAL_MAXIMUM(8, 1),

-	        HID_RI_PHYSICAL_MINIMUM(8, -1),

-	        HID_RI_PHYSICAL_MAXIMUM(8, 1),

-	        HID_RI_REPORT_COUNT(8, 0x02),

-	        HID_RI_REPORT_SIZE(8, 0x08),

-	        HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),

-	    HID_RI_END_COLLECTION(0),

-	HID_RI_END_COLLECTION(0),

-};

-

-/** Same as the MouseReport structure, but defines the keyboard HID interface's report structure. */

-const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =

-{

-	HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */

-	HID_RI_USAGE(8, 0x06), /* Keyboard */

-	HID_RI_COLLECTION(8, 0x01), /* Application */

-	    HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */

-	    HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */

-	    HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */

-	    HID_RI_LOGICAL_MINIMUM(8, 0x00),

-	    HID_RI_LOGICAL_MAXIMUM(8, 0x01),

-	    HID_RI_REPORT_SIZE(8, 0x01),

-	    HID_RI_REPORT_COUNT(8, 0x08),

-	    HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),

-	    HID_RI_REPORT_COUNT(8, 0x01),

-	    HID_RI_REPORT_SIZE(8, 0x08),

-	    HID_RI_INPUT(8, HID_IOF_CONSTANT),

-	    HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */

-	    HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */

-	    HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */

-	    HID_RI_REPORT_COUNT(8, 0x05),

-	    HID_RI_REPORT_SIZE(8, 0x01),

-	    HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),

-	    HID_RI_REPORT_COUNT(8, 0x01),

-	    HID_RI_REPORT_SIZE(8, 0x03),

-	    HID_RI_OUTPUT(8, HID_IOF_CONSTANT),

-	    HID_RI_LOGICAL_MINIMUM(8, 0x00),

-	    HID_RI_LOGICAL_MAXIMUM(8, 0x65),

-	    HID_RI_USAGE_PAGE(8, 0x07), /* Keyboard */

-	    HID_RI_USAGE_MINIMUM(8, 0x00), /* Reserved (no event indicated) */

-	    HID_RI_USAGE_MAXIMUM(8, 0x65), /* Keyboard Application */

-	    HID_RI_REPORT_COUNT(8, 0x06),

-	    HID_RI_REPORT_SIZE(8, 0x08),

-	    HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),

-	HID_RI_END_COLLECTION(0),

-};

-

-/** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall

- *  device characteristics, including the supported USB version, control endpoint size and the

- *  number of device configurations. The descriptor is read out by the USB host when the enumeration

- *  process begins.

- */

-const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =

-{

-	.Header                 = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},

-

-	.USBSpecification       = VERSION_BCD(01.10),

-	.Class                  = USB_CSCP_NoDeviceClass,

-	.SubClass               = USB_CSCP_NoDeviceSubclass,

-	.Protocol               = USB_CSCP_NoDeviceProtocol,

-

-	.Endpoint0Size          = FIXED_CONTROL_ENDPOINT_SIZE,

-

-	.VendorID               = 0x03EB,

-	.ProductID              = 0x204D,

-	.ReleaseNumber          = VERSION_BCD(00.01),

-

-	.ManufacturerStrIndex   = 0x01,

-	.ProductStrIndex        = 0x02,

-	.SerialNumStrIndex      = NO_DESCRIPTOR,

-

-	.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS

-};

-

-/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage

- *  of the device in one of its supported configurations, including information about any device interfaces

- *  and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting

- *  a configuration so that the host may correctly communicate with the USB device.

- */

-const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =

-{

-	.Config =

-		{

-			.Header                 = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},

-

-			.TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),

-			.TotalInterfaces        = 2,

-

-			.ConfigurationNumber    = 1,

-			.ConfigurationStrIndex  = NO_DESCRIPTOR,

-

-			.ConfigAttributes       = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_SELFPOWERED),

-

-			.MaxPowerConsumption    = USB_CONFIG_POWER_MA(100)

-		},

-

-	.HID1_KeyboardInterface =

-		{

-			.Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},

-

-			.InterfaceNumber        = 0x00,

-			.AlternateSetting       = 0x00,

-

-			.TotalEndpoints         = 2,

-

-			.Class                  = HID_CSCP_HIDClass,

-			.SubClass               = HID_CSCP_BootSubclass,

-			.Protocol               = HID_CSCP_KeyboardBootProtocol,

-

-			.InterfaceStrIndex      = NO_DESCRIPTOR

-		},

-

-	.HID1_KeyboardHID =

-		{

-			.Header                 = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},

-

-			.HIDSpec                = VERSION_BCD(01.11),

-			.CountryCode            = 0x00,

-			.TotalReportDescriptors = 1,

-			.HIDReportType          = HID_DTYPE_Report,

-			.HIDReportLength        = sizeof(KeyboardReport)

-		},

-

-	.HID1_ReportINEndpoint =

-		{

-			.Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},

-

-			.EndpointAddress        = (ENDPOINT_DIR_IN | KEYBOARD_IN_EPNUM),

-			.Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),

-			.EndpointSize           = HID_EPSIZE,

-			.PollingIntervalMS      = 0x01

-		},

-

-	.HID1_ReportOUTEndpoint =

-		{

-			.Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},

-

-			.EndpointAddress        = (ENDPOINT_DIR_OUT | KEYBOARD_OUT_EPNUM),

-			.Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),

-			.EndpointSize           = HID_EPSIZE,

-			.PollingIntervalMS      = 0x01

-		},

-

-	.HID2_MouseInterface =

-		{

-			.Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},

-

-			.InterfaceNumber        = 0x01,

-			.AlternateSetting       = 0x00,

-

-			.TotalEndpoints         = 1,

-

-			.Class                  = HID_CSCP_HIDClass,

-			.SubClass               = HID_CSCP_BootSubclass,

-			.Protocol               = HID_CSCP_MouseBootProtocol,

-

-			.InterfaceStrIndex      = NO_DESCRIPTOR

-		},

-

-	.HID2_MouseHID =

-		{

-			.Header                 = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},

-

-			.HIDSpec                = VERSION_BCD(01.11),

-			.CountryCode            = 0x00,

-			.TotalReportDescriptors = 1,

-			.HIDReportType          = HID_DTYPE_Report,

-			.HIDReportLength        = sizeof(MouseReport)

-		},

-

-	.HID2_ReportINEndpoint =

-		{

-			.Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},

-

-			.EndpointAddress        = (ENDPOINT_DIR_IN | MOUSE_IN_EPNUM),

-			.Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),

-			.EndpointSize           = HID_EPSIZE,

-			.PollingIntervalMS      = 0x01

-		}

-};

-

-/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests

- *  the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate

- *  via the language ID table available at USB.org what languages the device supports for its string descriptors.

- */

-const USB_Descriptor_String_t PROGMEM LanguageString =

-{

-	.Header                 = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},

-

-	.UnicodeString          = {LANGUAGE_ID_ENG}

-};

-

-/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable

- *  form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device

- *  Descriptor.

- */

-const USB_Descriptor_String_t PROGMEM ManufacturerString =

-{

-	.Header                 = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String},

-

-	.UnicodeString          = L"Dean Camera"

-};

-

-/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,

- *  and is read out upon request by the host when the appropriate string ID is requested, listed in the Device

- *  Descriptor.

- */

-const USB_Descriptor_String_t PROGMEM ProductString =

-{

-	.Header                 = {.Size = USB_STRING_LEN(28), .Type = DTYPE_String},

-

-	.UnicodeString          = L"LUFA Mouse and Keyboard Demo"

-};

-

-/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"

- *  documentation) by the application code so that the address and size of a requested descriptor can be given

- *  to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function

- *  is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the

- *  USB host.

- */

-uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,

-                                    const uint8_t wIndex,

-                                    const void** const DescriptorAddress)

-{

-	const uint8_t  DescriptorType   = (wValue >> 8);

-	const uint8_t  DescriptorNumber = (wValue & 0xFF);

-

-	const void* Address = NULL;

-	uint16_t    Size    = NO_DESCRIPTOR;

-

-	switch (DescriptorType)

-	{

-		case DTYPE_Device:

-			Address = &DeviceDescriptor;

-			Size    = sizeof(USB_Descriptor_Device_t);

-			break;

-		case DTYPE_Configuration:

-			Address = &ConfigurationDescriptor;

-			Size    = sizeof(USB_Descriptor_Configuration_t);

-			break;

-		case DTYPE_String:

-			switch (DescriptorNumber)

-			{

-				case 0x00:

-					Address = &LanguageString;

-					Size    = pgm_read_byte(&LanguageString.Header.Size);

-					break;

-				case 0x01:

-					Address = &ManufacturerString;

-					Size    = pgm_read_byte(&ManufacturerString.Header.Size);

-					break;

-				case 0x02:

-					Address = &ProductString;

-					Size    = pgm_read_byte(&ProductString.Header.Size);

-					break;

-			}

-

-			break;

-		case HID_DTYPE_HID:

-			if (!(wIndex))

-			{

-				Address = &ConfigurationDescriptor.HID1_KeyboardHID;

-				Size    = sizeof(USB_HID_Descriptor_HID_t);

-			}

-			else

-			{

-				Address = &ConfigurationDescriptor.HID2_MouseHID;

-				Size    = sizeof(USB_HID_Descriptor_HID_t);

-			}

-			break;

-		case HID_DTYPE_Report:

-			if (!(wIndex))

-			{

-				Address = &KeyboardReport;

-				Size    = sizeof(KeyboardReport);

-			}

-			else

-			{

-				Address = &MouseReport;

-				Size    = sizeof(MouseReport);

-			}

-

-			break;

-	}

-

-	*DescriptorAddress = Address;

-	return Size;

-}

-

+/* 
+ * Copyright 2012 Jun Wako <wakojun@gmail.com>
+ * This file is based on:
+ *     LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse
+ *     LUFA-120219/Demos/Device/Lowlevel/GenericHID
+ */
+
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2012.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2012  Dean Camera (dean [at] fourwalledcubicle [dot] com)
+  Copyright 2010  Denver Gingerich (denver [at] ossguy [dot] com)
+
+  Permission to use, copy, modify, distribute, and sell this
+  software and its documentation for any purpose is hereby granted
+  without fee, provided that the above copyright notice appear in
+  all copies and that both that the copyright notice and this
+  permission notice and warranty disclaimer appear in supporting
+  documentation, and that the name of the author not be used in
+  advertising or publicity pertaining to distribution of the
+  software without specific, written prior permission.
+
+  The author disclaim all warranties with regard to this
+  software, including all implied warranties of merchantability
+  and fitness.  In no event shall the author be liable for any
+  special, indirect or consequential damages or any damages
+  whatsoever resulting from loss of use, data or profits, whether
+  in an action of contract, negligence or other tortious action,
+  arising out of or in connection with the use or performance of
+  this software.
+*/
+
+/** \file
+ *
+ *  USB Device Descriptors, for library use when in USB device mode. Descriptors are special
+ *  computer-readable structures which the host requests upon device enumeration, to determine
+ *  the device's capabilities and functions.
+ */
+
+#include "Descriptors.h"
+
+
+/*******************************************************************************
+ * HID Report Descriptors
+ ******************************************************************************/
+const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
+{
+    HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
+    HID_RI_USAGE(8, 0x06), /* Keyboard */
+    HID_RI_COLLECTION(8, 0x01), /* Application */
+        HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
+        HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */
+        HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */
+        HID_RI_LOGICAL_MINIMUM(8, 0x00),
+        HID_RI_LOGICAL_MAXIMUM(8, 0x01),
+        HID_RI_REPORT_SIZE(8, 0x01),
+        HID_RI_REPORT_COUNT(8, 0x08),
+        HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+        HID_RI_REPORT_COUNT(8, 0x01),
+        HID_RI_REPORT_SIZE(8, 0x08),
+        HID_RI_INPUT(8, HID_IOF_CONSTANT),
+        HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
+        HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */
+        HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */
+        HID_RI_REPORT_COUNT(8, 0x05),
+        HID_RI_REPORT_SIZE(8, 0x01),
+        HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
+        HID_RI_REPORT_COUNT(8, 0x01),
+        HID_RI_REPORT_SIZE(8, 0x03),
+        HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
+        HID_RI_LOGICAL_MINIMUM(8, 0x00),
+        HID_RI_LOGICAL_MAXIMUM(8, 0x65),
+        HID_RI_USAGE_PAGE(8, 0x07), /* Keyboard */
+        HID_RI_USAGE_MINIMUM(8, 0x00), /* Reserved (no event indicated) */
+        HID_RI_USAGE_MAXIMUM(8, 0x65), /* Keyboard Application */
+        HID_RI_REPORT_COUNT(8, 0x06),
+        HID_RI_REPORT_SIZE(8, 0x08),
+        HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
+    HID_RI_END_COLLECTION(0),
+};
+
+const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] =
+{
+    HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
+    HID_RI_USAGE(8, 0x02), /* Mouse */
+    HID_RI_COLLECTION(8, 0x01), /* Application */
+        HID_RI_USAGE(8, 0x01), /* Pointer */
+        HID_RI_COLLECTION(8, 0x00), /* Physical */
+            HID_RI_USAGE_PAGE(8, 0x09), /* Button */
+            HID_RI_USAGE_MINIMUM(8, 0x01),
+            HID_RI_USAGE_MAXIMUM(8, 0x03),
+            HID_RI_LOGICAL_MINIMUM(8, 0x00),
+            HID_RI_LOGICAL_MAXIMUM(8, 0x01),
+            HID_RI_REPORT_COUNT(8, 0x03),
+            HID_RI_REPORT_SIZE(8, 0x01),
+            HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+            HID_RI_REPORT_COUNT(8, 0x01),
+            HID_RI_REPORT_SIZE(8, 0x05),
+            HID_RI_INPUT(8, HID_IOF_CONSTANT),
+            HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
+            HID_RI_USAGE(8, 0x30), /* Usage X */
+            HID_RI_USAGE(8, 0x31), /* Usage Y */
+            HID_RI_LOGICAL_MINIMUM(8, -1),
+            HID_RI_LOGICAL_MAXIMUM(8, 1),
+            HID_RI_PHYSICAL_MINIMUM(8, -1),
+            HID_RI_PHYSICAL_MAXIMUM(8, 1),
+            HID_RI_REPORT_COUNT(8, 0x02),
+            HID_RI_REPORT_SIZE(8, 0x08),
+            HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
+        HID_RI_END_COLLECTION(0),
+    HID_RI_END_COLLECTION(0),
+};
+
+const USB_Descriptor_HIDReport_Datatype_t PROGMEM GenericReport[] =
+{
+    HID_RI_USAGE_PAGE(16, 0xFF00), /* Vendor Page 0 */
+    HID_RI_USAGE(8, 0x01), /* Vendor Usage 1 */
+    HID_RI_COLLECTION(8, 0x01), /* Vendor Usage 1 */
+        HID_RI_USAGE(8, 0x02), /* Vendor Usage 2 */
+        HID_RI_LOGICAL_MINIMUM(8, 0x00),
+        HID_RI_LOGICAL_MAXIMUM(8, 0xFF),
+        HID_RI_REPORT_SIZE(8, 0x08),
+        HID_RI_REPORT_COUNT(8, GENERIC_REPORT_SIZE),
+        HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+        HID_RI_USAGE(8, 0x03), /* Vendor Usage 3 */
+        HID_RI_LOGICAL_MINIMUM(8, 0x00),
+        HID_RI_LOGICAL_MAXIMUM(8, 0xFF),
+        HID_RI_REPORT_SIZE(8, 0x08),
+        HID_RI_REPORT_COUNT(8, GENERIC_REPORT_SIZE),
+        HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
+    HID_RI_END_COLLECTION(0),
+};
+
+
+/*******************************************************************************
+ * Device Descriptors
+ ******************************************************************************/
+const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
+{
+    .Header                 = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
+
+    .USBSpecification       = VERSION_BCD(01.10),
+    .Class                  = USB_CSCP_NoDeviceClass,
+    .SubClass               = USB_CSCP_NoDeviceSubclass,
+    .Protocol               = USB_CSCP_NoDeviceProtocol,
+
+    .Endpoint0Size          = FIXED_CONTROL_ENDPOINT_SIZE,
+
+    .VendorID               = 0xFEED,
+    .ProductID              = 0x204D,
+    .ReleaseNumber          = VERSION_BCD(00.02),
+
+    .ManufacturerStrIndex   = 0x01,
+    .ProductStrIndex        = 0x02,
+    .SerialNumStrIndex      = NO_DESCRIPTOR,
+
+    .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
+};
+
+/*******************************************************************************
+ * Configuration Descriptors
+ ******************************************************************************/
+const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
+{
+    .Config =
+        {
+            .Header                 = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
+
+            .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
+            .TotalInterfaces        = 3,
+
+            .ConfigurationNumber    = 1,
+            .ConfigurationStrIndex  = NO_DESCRIPTOR,
+
+            .ConfigAttributes       = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_SELFPOWERED), //TODO: bus powered?
+
+            .MaxPowerConsumption    = USB_CONFIG_POWER_MA(100)
+        },
+
+        /*
+         * Keyboard
+         */
+    .HID1_KeyboardInterface =
+        {
+            .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+            .InterfaceNumber        = 0x00,
+            .AlternateSetting       = 0x00,
+
+            .TotalEndpoints         = 2,
+
+            .Class                  = HID_CSCP_HIDClass,
+            .SubClass               = HID_CSCP_BootSubclass,
+            .Protocol               = HID_CSCP_KeyboardBootProtocol,
+
+            .InterfaceStrIndex      = NO_DESCRIPTOR
+        },
+
+    .HID1_KeyboardHID =
+        {
+            .Header                 = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
+
+            .HIDSpec                = VERSION_BCD(01.11),
+            .CountryCode            = 0x00,
+            .TotalReportDescriptors = 1,
+            .HIDReportType          = HID_DTYPE_Report,
+            .HIDReportLength        = sizeof(KeyboardReport)
+        },
+
+    .HID1_ReportINEndpoint =
+        {
+            .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+            .EndpointAddress        = (ENDPOINT_DIR_IN | KEYBOARD_IN_EPNUM),
+            .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+            .EndpointSize           = HID_EPSIZE,
+            .PollingIntervalMS      = 0x01
+        },
+
+    .HID1_ReportOUTEndpoint =
+        {
+            .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+            .EndpointAddress        = (ENDPOINT_DIR_OUT | KEYBOARD_OUT_EPNUM),
+            .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+            .EndpointSize           = HID_EPSIZE,
+            .PollingIntervalMS      = 0x01
+        },
+
+    /*
+     * Mouse
+     */
+    .HID2_MouseInterface =
+        {
+            .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+            .InterfaceNumber        = 0x01,
+            .AlternateSetting       = 0x00,
+
+            .TotalEndpoints         = 1,
+
+            .Class                  = HID_CSCP_HIDClass,
+            .SubClass               = HID_CSCP_BootSubclass,
+            .Protocol               = HID_CSCP_MouseBootProtocol,
+
+            .InterfaceStrIndex      = NO_DESCRIPTOR
+        },
+
+    .HID2_MouseHID =
+        {
+            .Header                 = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
+
+            .HIDSpec                = VERSION_BCD(01.11),
+            .CountryCode            = 0x00,
+            .TotalReportDescriptors = 1,
+            .HIDReportType          = HID_DTYPE_Report,
+            .HIDReportLength        = sizeof(MouseReport)
+        },
+
+    .HID2_ReportINEndpoint =
+        {
+            .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+            .EndpointAddress        = (ENDPOINT_DIR_IN | MOUSE_IN_EPNUM),
+            .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+            .EndpointSize           = HID_EPSIZE,
+            .PollingIntervalMS      = 0x01
+        },
+
+    /*
+     * Generic
+     */
+    .HID3_GenericInterface =
+        {
+            .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+            .InterfaceNumber        = 0x02,
+            .AlternateSetting       = 0x00,
+
+            .TotalEndpoints         = 2,
+
+            .Class                  = HID_CSCP_HIDClass,
+            .SubClass               = HID_CSCP_NonBootSubclass,
+            .Protocol               = HID_CSCP_NonBootProtocol,
+
+            .InterfaceStrIndex      = NO_DESCRIPTOR
+        },
+
+    .HID3_GenericHID =
+        {
+            .Header                 = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
+
+            .HIDSpec                = VERSION_BCD(01.11),
+            .CountryCode            = 0x00,
+            .TotalReportDescriptors = 1,
+            .HIDReportType          = HID_DTYPE_Report,
+            .HIDReportLength        = sizeof(GenericReport)
+        },
+
+    .HID3_ReportINEndpoint =
+        {
+            .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+            .EndpointAddress        = (ENDPOINT_DIR_IN | GENERIC_IN_EPNUM),
+            .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+            .EndpointSize           = GENERIC_EPSIZE,
+            .PollingIntervalMS      = 0x01
+        },
+
+    .HID3_ReportOUTEndpoint =
+        {
+            .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+            .EndpointAddress        = (ENDPOINT_DIR_OUT | GENERIC_OUT_EPNUM),
+            .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+            .EndpointSize           = GENERIC_EPSIZE,
+            .PollingIntervalMS      = 0x01
+        }
+};
+
+
+/*******************************************************************************
+ * String Descriptors
+ ******************************************************************************/
+const USB_Descriptor_String_t PROGMEM LanguageString =
+{
+    .Header                 = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
+
+    .UnicodeString          = {LANGUAGE_ID_ENG}
+};
+
+const USB_Descriptor_String_t PROGMEM ManufacturerString =
+{
+    .Header                 = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String},
+
+    .UnicodeString          = L"Dean Camera"    // TODO:
+};
+
+const USB_Descriptor_String_t PROGMEM ProductString =
+{
+    .Header                 = {.Size = USB_STRING_LEN(28), .Type = DTYPE_String},
+
+    .UnicodeString          = L"LUFA Mouse and Keyboard Demo"   // TODO:
+};
+
+
+/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
+ *  documentation) by the application code so that the address and size of a requested descriptor can be given
+ *  to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
+ *  is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
+ *  USB host.
+ */
+uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+                                    const uint8_t wIndex,
+                                    const void** const DescriptorAddress)
+{
+    const uint8_t  DescriptorType   = (wValue >> 8);
+    const uint8_t  DescriptorIndex  = (wValue & 0xFF);
+
+    const void* Address = NULL;
+    uint16_t    Size    = NO_DESCRIPTOR;
+
+    switch (DescriptorType)
+    {
+        case DTYPE_Device:
+            Address = &DeviceDescriptor;
+            Size    = sizeof(USB_Descriptor_Device_t);
+            break;
+        case DTYPE_Configuration:
+            Address = &ConfigurationDescriptor;
+            Size    = sizeof(USB_Descriptor_Configuration_t);
+            break;
+        case DTYPE_String:
+            switch (DescriptorIndex )
+            {
+                case 0x00:
+                    Address = &LanguageString;
+                    Size    = pgm_read_byte(&LanguageString.Header.Size);
+                    break;
+                case 0x01:
+                    Address = &ManufacturerString;
+                    Size    = pgm_read_byte(&ManufacturerString.Header.Size);
+                    break;
+                case 0x02:
+                    Address = &ProductString;
+                    Size    = pgm_read_byte(&ProductString.Header.Size);
+                    break;
+            }
+            break;
+        case HID_DTYPE_HID:
+            switch (wIndex) {
+            case 0:
+                Address = &ConfigurationDescriptor.HID1_KeyboardHID;
+                Size    = sizeof(USB_HID_Descriptor_HID_t);
+                break;
+            case 1:
+                Address = &ConfigurationDescriptor.HID2_MouseHID;
+                Size    = sizeof(USB_HID_Descriptor_HID_t);
+                break;
+            case 2:
+                Address = &ConfigurationDescriptor.HID3_GenericHID;
+                Size    = sizeof(USB_HID_Descriptor_HID_t);
+                break;
+            }
+            break;
+        case HID_DTYPE_Report:
+            switch (wIndex) {
+            case 0:
+                Address = &KeyboardReport;
+                Size    = sizeof(KeyboardReport);
+                break;
+            case 1:
+                Address = &MouseReport;
+                Size    = sizeof(MouseReport);
+                break;
+            case 2:
+                Address = &GenericReport;
+                Size    = sizeof(GenericReport);
+                break;
+            }
+            break;
+    }
+
+    *DescriptorAddress = Address;
+    return Size;
+}
diff --git a/keyboard/lufa/Descriptors.h b/keyboard/lufa/Descriptors.h
index 05b2035bb1..03e2426a37 100644
--- a/keyboard/lufa/Descriptors.h
+++ b/keyboard/lufa/Descriptors.h
@@ -37,51 +37,48 @@
 #ifndef _DESCRIPTORS_H_

 #define _DESCRIPTORS_H_

 

-	/* Includes: */

-		#include <LUFA/Drivers/USB/USB.h>

-

-		#include <avr/pgmspace.h>

-

-	/* Type Defines: */

-		/** Type define for the device configuration descriptor structure. This must be defined in the

-		 *  application code, as the configuration descriptor contains several sub-descriptors which

-		 *  vary between devices, and which describe the device's usage to the host.

-		 */

-		typedef struct

-		{

-			USB_Descriptor_Configuration_Header_t Config;

-

-			// Keyboard HID Interface

-			USB_Descriptor_Interface_t            HID1_KeyboardInterface;

-			USB_HID_Descriptor_HID_t              HID1_KeyboardHID;

-			USB_Descriptor_Endpoint_t             HID1_ReportINEndpoint;

-			USB_Descriptor_Endpoint_t             HID1_ReportOUTEndpoint;

-

-			// Mouse HID Interface

-			USB_Descriptor_Interface_t            HID2_MouseInterface;

-			USB_HID_Descriptor_HID_t              HID2_MouseHID;

-			USB_Descriptor_Endpoint_t             HID2_ReportINEndpoint;

-			USB_Descriptor_Endpoint_t             HID2_ReportOUTEndpoint;

-		} USB_Descriptor_Configuration_t;

-

-	/* Macros: */

-		/** 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

-

-		/** Size in bytes of each of the HID reporting IN and OUT endpoints. */

-		#define HID_EPSIZE                8

-

-	/* Function Prototypes: */

-		uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,

-		                                    const uint8_t wIndex,

-		                                    const void** const DescriptorAddress)

-		                                    ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);

+#include <LUFA/Drivers/USB/USB.h>

+#include <avr/pgmspace.h>

+

+

+typedef struct

+{

+    USB_Descriptor_Configuration_Header_t Config;

+

+    // Keyboard HID Interface

+    USB_Descriptor_Interface_t            HID1_KeyboardInterface;

+    USB_HID_Descriptor_HID_t              HID1_KeyboardHID;

+    USB_Descriptor_Endpoint_t             HID1_ReportINEndpoint;

+    USB_Descriptor_Endpoint_t             HID1_ReportOUTEndpoint;

+

+    // Mouse HID Interface

+    USB_Descriptor_Interface_t            HID2_MouseInterface;

+    USB_HID_Descriptor_HID_t              HID2_MouseHID;

+    USB_Descriptor_Endpoint_t             HID2_ReportINEndpoint;

+

+    // Generic HID Interface

+    USB_Descriptor_Interface_t            HID3_GenericInterface;

+    USB_HID_Descriptor_HID_t              HID3_GenericHID;

+    USB_Descriptor_Endpoint_t             HID3_ReportINEndpoint;

+    USB_Descriptor_Endpoint_t             HID3_ReportOUTEndpoint;

+} USB_Descriptor_Configuration_t;

 

-#endif

 

+// Endopoint number/size

+#define KEYBOARD_IN_EPNUM         1

+#define KEYBOARD_OUT_EPNUM        2

+#define MOUSE_IN_EPNUM            3

+#define GENERIC_IN_EPNUM          4

+#define GENERIC_OUT_EPNUM         5

+

+#define HID_EPSIZE                8

+#define GENERIC_EPSIZE            8

+#define GENERIC_REPORT_SIZE       8

+

+

+uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,

+                                    const uint8_t wIndex,

+                                    const void** const DescriptorAddress)

+                                    ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);

+

+#endif

diff --git a/keyboard/lufa/Makefile b/keyboard/lufa/Makefile
index 1d2f712d4a..115c7e6ec6 100644
--- a/keyboard/lufa/Makefile
+++ b/keyboard/lufa/Makefile
@@ -128,8 +128,7 @@ LSRC = $(TARGET).c                                                 \
 SRC = $(subst $(LUFA_PATH)/LUFA/,,$(LSRC))

 SRC +=	keymap.c \

 	matrix.c \

-	led.c \

-	sendchar_null.c

+	led.c

 CONFIG_H = config.h

 

 

diff --git a/keyboard/lufa/lufa.c b/keyboard/lufa/lufa.c
index d7e7c1654d..d841f45c6a 100644
--- a/keyboard/lufa/lufa.c
+++ b/keyboard/lufa/lufa.c
@@ -1,6 +1,8 @@
 /* 
  * Copyright 2012 Jun Wako <wakojun@gmail.com>
- * This file is based on LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse.
+ * This file is based on:
+ *     LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse
+ *     LUFA-120219/Demos/Device/Lowlevel/GenericHID
  */
 
 /*
@@ -38,6 +40,8 @@
 #include "host.h"
 #include "host_driver.h"
 #include "keyboard.h"
+#include "sendchar.h"
+#include "debug.h"
 #include "lufa.h"
 
 static uint8_t keyboard_led_stats = 0;
@@ -64,11 +68,21 @@ int main(void)
     SetupHardware();
     sei();
 
+    print_enable = true;
+    debug_enable = true;
+    debug_matrix = true;
+    debug_keyboard = true;
+    debug_mouse = true;
+
+    _delay_ms(3000);
+    print("abcdefg\n");
+
     keyboard_init();
     host_set_driver(&lufa_driver);
     while (1) {
         keyboard_proc();
         Keyboard_HID_Task();
+        Generic_HID_Task();
         USB_USBTask();
     }
 }
@@ -112,6 +126,12 @@ void EVENT_USB_Device_ConfigurationChanged(void)
     /* Setup Mouse HID Report Endpoint */
     ConfigSuccess &= Endpoint_ConfigureEndpoint(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
                                                 HID_EPSIZE, ENDPOINT_BANK_SINGLE);
+
+	/* Setup Generic HID Report Endpoints */
+	ConfigSuccess &= Endpoint_ConfigureEndpoint(GENERIC_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
+	                                            GENERIC_EPSIZE, ENDPOINT_BANK_SINGLE);
+	ConfigSuccess &= Endpoint_ConfigureEndpoint(GENERIC_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
+	                                            GENERIC_EPSIZE, ENDPOINT_BANK_SINGLE);
 }
 
 /** Event handler for the USB_ControlRequest event.
@@ -119,8 +139,8 @@ void EVENT_USB_Device_ConfigurationChanged(void)
  */
 void EVENT_USB_Device_ControlRequest(void)
 {
-    uint8_t* ReportData;
-    uint8_t  ReportSize;
+    uint8_t* ReportData = NULL;
+    uint8_t  ReportSize = 0;
 
     /* Handle HID Class specific requests */
     switch (USB_ControlRequest.bRequest)
@@ -130,16 +150,18 @@ void EVENT_USB_Device_ControlRequest(void)
             {
                 Endpoint_ClearSETUP();
 
-                /* Determine if it is the mouse or the keyboard data that is being requested */
-                if (!(USB_ControlRequest.wIndex))
-                {
+                // Interface
+                switch (USB_ControlRequest.wIndex) {
+                case 1: // Keyboard
                     ReportData = (uint8_t*)&keyboard_report_sent;
                     ReportSize = sizeof(keyboard_report_sent);
-                }
-                else
-                {
+                    break;
+                case 2: // Mouse
                     ReportData = (uint8_t*)&mouse_report_sent;
                     ReportSize = sizeof(mouse_report_sent);
+                    break;
+                case 3: // Generic
+                    break;
                 }
 
                 /* Write the report data to the control endpoint */
@@ -160,8 +182,17 @@ void EVENT_USB_Device_ControlRequest(void)
                       return;
                 }
 
-                /* Read in the LED report from the host */
-                keyboard_led_stats = Endpoint_Read_8();
+                // Interface
+                switch (USB_ControlRequest.wIndex) {
+                case 1: // Keyboard
+                    /* Read in the LED report from the host */
+                    keyboard_led_stats = Endpoint_Read_8();
+                    break;
+                case 2: // Mouse
+                    break;
+                case 3: // Generic
+                    break;
+                }
 
                 Endpoint_ClearOUT();
                 Endpoint_ClearStatusStage();
@@ -176,6 +207,10 @@ void EVENT_USB_Device_ControlRequest(void)
  */
 void Keyboard_HID_Task(void)
 {
+	/* Device must be connected and configured for the task to run */
+	if (USB_DeviceState != DEVICE_STATE_Configured)
+	  return;
+
     /* Select the Keyboard LED Report Endpoint */
     Endpoint_SelectEndpoint(KEYBOARD_OUT_EPNUM);
 
@@ -190,6 +225,40 @@ void Keyboard_HID_Task(void)
     }
 }
 
+void Generic_HID_Task(void)
+{
+	/* Device must be connected and configured for the task to run */
+	if (USB_DeviceState != DEVICE_STATE_Configured)
+	  return;
+
+	Endpoint_SelectEndpoint(GENERIC_OUT_EPNUM);
+
+	/* Check to see if a packet has been sent from the host */
+	if (Endpoint_IsOUTReceived())
+	{
+		/* Check to see if the packet contains data */
+		if (Endpoint_IsReadWriteAllowed())
+		{
+			/* Create a temporary buffer to hold the read in report from the host */
+			uint8_t GenericData[GENERIC_REPORT_SIZE];
+
+			/* Read Generic Report Data */
+			Endpoint_Read_Stream_LE(&GenericData, sizeof(GenericData), NULL);
+
+			/* Process Generic Report Data */
+			//TODO: ProcessGenericHIDReport(GenericData);
+		}
+
+		/* Finalize the stream transfer to send the last packet */
+		Endpoint_ClearOUT();
+	}
+
+        /* IN packet */
+	Endpoint_SelectEndpoint(GENERIC_IN_EPNUM);
+        // send IN packet
+	if (Endpoint_IsINReady())
+            Endpoint_ClearIN();
+}
 
 /*******************************************************************************
  * Host driver 
@@ -241,3 +310,41 @@ static void send_system(uint16_t data)
 static void send_consumer(uint16_t data)
 {
 }
+
+
+/*******************************************************************************
+ * sendchar
+ ******************************************************************************/
+int8_t sendchar(uint8_t c)
+{
+    if (USB_DeviceState != DEVICE_STATE_Configured)
+      return -1;
+
+    Endpoint_SelectEndpoint(GENERIC_IN_EPNUM);
+
+    uint8_t timeout = 10;
+    uint16_t prevFN = USB_Device_GetFrameNumber();
+    while (!Endpoint_IsINReady()) {
+        switch (USB_DeviceState) {
+        case DEVICE_STATE_Unattached:
+        case DEVICE_STATE_Suspended:
+            return -1;
+        }
+        if (Endpoint_IsStalled())
+            return -1;
+        uint16_t currFN = USB_Device_GetFrameNumber();
+        if (prevFN != USB_Device_GetFrameNumber()) {
+            if (!(timeout--))
+                return -1;
+            prevFN = USB_Device_GetFrameNumber();
+        }
+    }
+
+    Endpoint_Write_8(c);
+
+    // send when packet is full
+    if (!Endpoint_IsReadWriteAllowed())
+        Endpoint_ClearIN();
+
+    return 0;
+}
diff --git a/keyboard/lufa/lufa.h b/keyboard/lufa/lufa.h
index 74fe0b72f1..3ba14b360b 100644
--- a/keyboard/lufa/lufa.h
+++ b/keyboard/lufa/lufa.h
@@ -65,7 +65,7 @@
 		void SetupHardware(void);

 		void Keyboard_ProcessLEDReport(const uint8_t LEDStatus);

 		void Keyboard_HID_Task(void);

-		void Mouse_HID_Task(void);

+		void Generic_HID_Task(void);

 

 		void EVENT_USB_Device_Connect(void);

 		void EVENT_USB_Device_Disconnect(void);