Index: grip2hid/Config/LUFAConfig.h
===================================================================
--- grip2hid/Config/LUFAConfig.h	(revision 703832c006eb1d6b9c500dead75987968fae6928)
+++ grip2hid/Config/LUFAConfig.h	(revision 703832c006eb1d6b9c500dead75987968fae6928)
@@ -0,0 +1,126 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2021.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2021  Dean Camera (dean [at] fourwalledcubicle [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 disclaims 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
+ *  \brief LUFA Library Configuration Header File
+ *
+ *  This header file is used to configure LUFA's compile time options,
+ *  as an alternative to the compile time constants supplied through
+ *  a makefile.
+ *
+ *  For information on what each token does, refer to the LUFA
+ *  manual section "Summary of Compile Tokens".
+ */
+
+#ifndef _LUFA_CONFIG_H_
+#define _LUFA_CONFIG_H_
+
+	#if (ARCH == ARCH_AVR8)
+
+		/* Non-USB Related Configuration Tokens: */
+//		#define DISABLE_TERMINAL_CODES
+
+		/* USB Class Driver Related Tokens: */
+//		#define HID_HOST_BOOT_PROTOCOL_ONLY
+//		#define HID_STATETABLE_STACK_DEPTH       {Insert Value Here}
+//		#define HID_USAGE_STACK_DEPTH            {Insert Value Here}
+//		#define HID_MAX_COLLECTIONS              {Insert Value Here}
+//		#define HID_MAX_REPORTITEMS              {Insert Value Here}
+//		#define HID_MAX_REPORT_IDS               {Insert Value Here}
+//		#define NO_CLASS_DRIVER_AUTOFLUSH
+
+		/* General USB Driver Related Tokens: */
+//		#define ORDERED_EP_CONFIG
+		#define USE_STATIC_OPTIONS               (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
+		#define USB_DEVICE_ONLY
+//		#define USB_HOST_ONLY
+//		#define USB_STREAM_TIMEOUT_MS            {Insert Value Here}
+//		#define NO_LIMITED_CONTROLLER_CONNECT
+//		#define NO_SOF_EVENTS
+
+		/* USB Device Mode Driver Related Tokens: */
+//		#define USE_RAM_DESCRIPTORS
+		#define USE_FLASH_DESCRIPTORS
+//		#define USE_EEPROM_DESCRIPTORS
+//		#define NO_INTERNAL_SERIAL
+		#define FIXED_CONTROL_ENDPOINT_SIZE      8
+//		#define DEVICE_STATE_AS_GPIOR            {Insert Value Here}
+		#define FIXED_NUM_CONFIGURATIONS         1
+//		#define CONTROL_ONLY_DEVICE
+//		#define INTERRUPT_CONTROL_ENDPOINT
+//		#define NO_DEVICE_REMOTE_WAKEUP
+//		#define NO_DEVICE_SELF_POWER
+
+		/* USB Host Mode Driver Related Tokens: */
+//		#define HOST_STATE_AS_GPIOR              {Insert Value Here}
+//		#define USB_HOST_TIMEOUT_MS              {Insert Value Here}
+//		#define HOST_DEVICE_SETTLE_DELAY_MS	     {Insert Value Here}
+//		#define NO_AUTO_VBUS_MANAGEMENT
+//		#define INVERTED_VBUS_ENABLE_LINE
+
+	#elif (ARCH == ARCH_XMEGA)
+
+		/* Non-USB Related Configuration Tokens: */
+//		#define DISABLE_TERMINAL_CODES
+
+		/* USB Class Driver Related Tokens: */
+//		#define HID_HOST_BOOT_PROTOCOL_ONLY
+//		#define HID_STATETABLE_STACK_DEPTH       {Insert Value Here}
+//		#define HID_USAGE_STACK_DEPTH            {Insert Value Here}
+//		#define HID_MAX_COLLECTIONS              {Insert Value Here}
+//		#define HID_MAX_REPORTITEMS              {Insert Value Here}
+//		#define HID_MAX_REPORT_IDS               {Insert Value Here}
+//		#define NO_CLASS_DRIVER_AUTOFLUSH
+
+		/* General USB Driver Related Tokens: */
+		#define USE_STATIC_OPTIONS               (USB_DEVICE_OPT_FULLSPEED | USB_OPT_RC32MCLKSRC | USB_OPT_BUSEVENT_PRIHIGH)
+//		#define USB_STREAM_TIMEOUT_MS            {Insert Value Here}
+//		#define NO_LIMITED_CONTROLLER_CONNECT
+//		#define NO_SOF_EVENTS
+
+		/* USB Device Mode Driver Related Tokens: */
+//		#define USE_RAM_DESCRIPTORS
+		#define USE_FLASH_DESCRIPTORS
+//		#define USE_EEPROM_DESCRIPTORS
+//		#define NO_INTERNAL_SERIAL
+		#define FIXED_CONTROL_ENDPOINT_SIZE      8
+//		#define DEVICE_STATE_AS_GPIOR            {Insert Value Here}
+		#define FIXED_NUM_CONFIGURATIONS         1
+//		#define CONTROL_ONLY_DEVICE
+		#define MAX_ENDPOINT_INDEX               1
+//		#define NO_DEVICE_REMOTE_WAKEUP
+//		#define NO_DEVICE_SELF_POWER
+
+	#else
+
+		#error Unsupported architecture for this LUFA configuration file.
+
+	#endif
+#endif
Index: grip2hid/Descriptors.c
===================================================================
--- grip2hid/Descriptors.c	(revision 703832c006eb1d6b9c500dead75987968fae6928)
+++ grip2hid/Descriptors.c	(revision 703832c006eb1d6b9c500dead75987968fae6928)
@@ -0,0 +1,479 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2021.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2021  Dean Camera (dean [at] fourwalledcubicle [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 disclaims 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.
+ */
+const USB_Descriptor_HIDReport_Datatype_t PROGMEM JoystickReport[] =
+{
+			HID_RI_USAGE_PAGE(8, 0x01),
+			HID_RI_USAGE(8, 0x04),
+			HID_RI_COLLECTION(8, 0x01),
+
+				0x85, 0x01, // Report ID 1
+
+				// 15 constant bytes
+				HID_RI_REPORT_SIZE(8, 15),
+				HID_RI_REPORT_COUNT(8, 0x01),
+				HID_RI_INPUT(8, HID_IOF_CONSTANT),
+
+				HID_RI_USAGE_PAGE(8, 0x09),
+				HID_RI_LOGICAL_MINIMUM(8, 0x00),
+				HID_RI_LOGICAL_MAXIMUM(8, 0x01),
+
+				HID_RI_USAGE_MINIMUM(8, 7),
+				HID_RI_USAGE_MAXIMUM(8, 9),
+				HID_RI_USAGE(8, 4),
+				HID_RI_REPORT_SIZE(8, 0x01),
+				HID_RI_REPORT_COUNT(8, 4),
+				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+
+				HID_RI_REPORT_SIZE(8, 1),
+				HID_RI_REPORT_COUNT(8, 0x01),
+				HID_RI_INPUT(8, HID_IOF_CONSTANT),
+
+				HID_RI_USAGE(8, 10),
+				HID_RI_USAGE_MINIMUM(8, 1),
+				HID_RI_USAGE_MAXIMUM(8, 3),
+				HID_RI_REPORT_SIZE(8, 0x01),
+				HID_RI_REPORT_COUNT(8, 4),
+				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+
+				HID_RI_REPORT_SIZE(8, 1),
+				HID_RI_REPORT_COUNT(8, 0x01),
+				HID_RI_INPUT(8, HID_IOF_CONSTANT),
+
+				HID_RI_USAGE_MINIMUM(8, 5),
+				HID_RI_USAGE_MAXIMUM(8, 6),
+				HID_RI_REPORT_SIZE(8, 0x01),
+				HID_RI_REPORT_COUNT(8, 2),
+				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+
+				HID_RI_USAGE_PAGE(8, 0x01),
+				HID_RI_USAGE(8, 0x01),
+				HID_RI_COLLECTION(8, 0x00),
+					HID_RI_USAGE(8, 0x31),
+					HID_RI_LOGICAL_MINIMUM(8, -2),
+					HID_RI_LOGICAL_MAXIMUM(8, 1),
+					HID_RI_REPORT_COUNT(8, 1),
+					HID_RI_REPORT_SIZE(8, 2),
+					HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+
+					HID_RI_REPORT_SIZE(8, 1),
+					HID_RI_REPORT_COUNT(8, 0x01),
+					HID_RI_INPUT(8, HID_IOF_CONSTANT),
+
+					HID_RI_USAGE(8, 0x30),
+					HID_RI_LOGICAL_MINIMUM(8, -2),
+					HID_RI_LOGICAL_MAXIMUM(8, 1),
+					HID_RI_REPORT_COUNT(8, 1),
+					HID_RI_REPORT_SIZE(8, 2),
+					HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+				HID_RI_END_COLLECTION(0),
+
+			HID_RI_END_COLLECTION(0),
+
+			HID_RI_USAGE_PAGE(8, 0x01),
+			HID_RI_USAGE(8, 0x04),
+			HID_RI_COLLECTION(8, 0x01),
+
+				0x85, 0x02, // Report ID 2
+
+				// 15 constant bytes
+				HID_RI_REPORT_SIZE(8, 15),
+				HID_RI_REPORT_COUNT(8, 0x01),
+				HID_RI_INPUT(8, HID_IOF_CONSTANT),
+
+				HID_RI_USAGE_PAGE(8, 0x09),
+				HID_RI_LOGICAL_MINIMUM(8, 0x00),
+				HID_RI_LOGICAL_MAXIMUM(8, 0x01),
+
+				HID_RI_USAGE_MINIMUM(8, 7),
+				HID_RI_USAGE_MAXIMUM(8, 9),
+				HID_RI_USAGE(8, 4),
+				HID_RI_REPORT_SIZE(8, 0x01),
+				HID_RI_REPORT_COUNT(8, 4),
+				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+
+				HID_RI_REPORT_SIZE(8, 1),
+				HID_RI_REPORT_COUNT(8, 0x01),
+				HID_RI_INPUT(8, HID_IOF_CONSTANT),
+
+				HID_RI_USAGE(8, 10),
+				HID_RI_USAGE_MINIMUM(8, 1),
+				HID_RI_USAGE_MAXIMUM(8, 3),
+				HID_RI_REPORT_SIZE(8, 0x01),
+				HID_RI_REPORT_COUNT(8, 4),
+				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+
+				HID_RI_REPORT_SIZE(8, 1),
+				HID_RI_REPORT_COUNT(8, 0x01),
+				HID_RI_INPUT(8, HID_IOF_CONSTANT),
+
+				HID_RI_USAGE_MINIMUM(8, 5),
+				HID_RI_USAGE_MAXIMUM(8, 6),
+				HID_RI_REPORT_SIZE(8, 0x01),
+				HID_RI_REPORT_COUNT(8, 2),
+				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+
+				HID_RI_USAGE_PAGE(8, 0x01),
+				HID_RI_USAGE(8, 0x01),
+				HID_RI_COLLECTION(8, 0x00),
+					HID_RI_USAGE(8, 0x31),
+					HID_RI_LOGICAL_MINIMUM(8, -2),
+					HID_RI_LOGICAL_MAXIMUM(8, 1),
+					HID_RI_REPORT_COUNT(8, 1),
+					HID_RI_REPORT_SIZE(8, 2),
+					HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+
+					HID_RI_REPORT_SIZE(8, 1),
+					HID_RI_REPORT_COUNT(8, 0x01),
+					HID_RI_INPUT(8, HID_IOF_CONSTANT),
+
+					HID_RI_USAGE(8, 0x30),
+					HID_RI_LOGICAL_MINIMUM(8, -2),
+					HID_RI_LOGICAL_MAXIMUM(8, 1),
+					HID_RI_REPORT_COUNT(8, 1),
+					HID_RI_REPORT_SIZE(8, 2),
+					HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+				HID_RI_END_COLLECTION(0),
+
+			HID_RI_END_COLLECTION(0),
+
+			HID_RI_USAGE_PAGE(8, 0x01),
+			HID_RI_USAGE(8, 0x04),
+			HID_RI_COLLECTION(8, 0x01),
+
+				0x85, 0x03, // Report ID 3
+
+				// 15 constant bytes
+				HID_RI_REPORT_SIZE(8, 15),
+				HID_RI_REPORT_COUNT(8, 0x01),
+				HID_RI_INPUT(8, HID_IOF_CONSTANT),
+
+				HID_RI_USAGE_PAGE(8, 0x09),
+				HID_RI_LOGICAL_MINIMUM(8, 0x00),
+				HID_RI_LOGICAL_MAXIMUM(8, 0x01),
+
+				HID_RI_USAGE_MINIMUM(8, 7),
+				HID_RI_USAGE_MAXIMUM(8, 9),
+				HID_RI_USAGE(8, 4),
+				HID_RI_REPORT_SIZE(8, 0x01),
+				HID_RI_REPORT_COUNT(8, 4),
+				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+
+				HID_RI_REPORT_SIZE(8, 1),
+				HID_RI_REPORT_COUNT(8, 0x01),
+				HID_RI_INPUT(8, HID_IOF_CONSTANT),
+
+				HID_RI_USAGE(8, 10),
+				HID_RI_USAGE_MINIMUM(8, 1),
+				HID_RI_USAGE_MAXIMUM(8, 3),
+				HID_RI_REPORT_SIZE(8, 0x01),
+				HID_RI_REPORT_COUNT(8, 4),
+				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+
+				HID_RI_REPORT_SIZE(8, 1),
+				HID_RI_REPORT_COUNT(8, 0x01),
+				HID_RI_INPUT(8, HID_IOF_CONSTANT),
+
+				HID_RI_USAGE_MINIMUM(8, 5),
+				HID_RI_USAGE_MAXIMUM(8, 6),
+				HID_RI_REPORT_SIZE(8, 0x01),
+				HID_RI_REPORT_COUNT(8, 2),
+				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+
+				HID_RI_USAGE_PAGE(8, 0x01),
+				HID_RI_USAGE(8, 0x01),
+				HID_RI_COLLECTION(8, 0x00),
+					HID_RI_USAGE(8, 0x31),
+					HID_RI_LOGICAL_MINIMUM(8, -2),
+					HID_RI_LOGICAL_MAXIMUM(8, 1),
+					HID_RI_REPORT_COUNT(8, 1),
+					HID_RI_REPORT_SIZE(8, 2),
+					HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+
+					HID_RI_REPORT_SIZE(8, 1),
+					HID_RI_REPORT_COUNT(8, 0x01),
+					HID_RI_INPUT(8, HID_IOF_CONSTANT),
+
+					HID_RI_USAGE(8, 0x30),
+					HID_RI_LOGICAL_MINIMUM(8, -2),
+					HID_RI_LOGICAL_MAXIMUM(8, 1),
+					HID_RI_REPORT_COUNT(8, 1),
+					HID_RI_REPORT_SIZE(8, 2),
+					HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+				HID_RI_END_COLLECTION(0),
+
+			HID_RI_END_COLLECTION(0),
+
+			HID_RI_USAGE_PAGE(8, 0x01),
+			HID_RI_USAGE(8, 0x04),
+			HID_RI_COLLECTION(8, 0x01),
+
+				0x85, 0x04, // Report ID 4
+
+				// 15 constant bytes
+				HID_RI_REPORT_SIZE(8, 15),
+				HID_RI_REPORT_COUNT(8, 0x01),
+				HID_RI_INPUT(8, HID_IOF_CONSTANT),
+
+				HID_RI_USAGE_PAGE(8, 0x09),
+				HID_RI_LOGICAL_MINIMUM(8, 0x00),
+				HID_RI_LOGICAL_MAXIMUM(8, 0x01),
+
+				HID_RI_USAGE_MINIMUM(8, 7),
+				HID_RI_USAGE_MAXIMUM(8, 9),
+				HID_RI_USAGE(8, 4),
+				HID_RI_REPORT_SIZE(8, 0x01),
+				HID_RI_REPORT_COUNT(8, 4),
+				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+
+				HID_RI_REPORT_SIZE(8, 1),
+				HID_RI_REPORT_COUNT(8, 0x01),
+				HID_RI_INPUT(8, HID_IOF_CONSTANT),
+
+				HID_RI_USAGE(8, 10),
+				HID_RI_USAGE_MINIMUM(8, 1),
+				HID_RI_USAGE_MAXIMUM(8, 3),
+				HID_RI_REPORT_SIZE(8, 0x01),
+				HID_RI_REPORT_COUNT(8, 4),
+				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+
+				HID_RI_REPORT_SIZE(8, 1),
+				HID_RI_REPORT_COUNT(8, 0x01),
+				HID_RI_INPUT(8, HID_IOF_CONSTANT),
+
+				HID_RI_USAGE_MINIMUM(8, 5),
+				HID_RI_USAGE_MAXIMUM(8, 6),
+				HID_RI_REPORT_SIZE(8, 0x01),
+				HID_RI_REPORT_COUNT(8, 2),
+				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+
+				HID_RI_USAGE_PAGE(8, 0x01),
+				HID_RI_USAGE(8, 0x01),
+				HID_RI_COLLECTION(8, 0x00),
+					HID_RI_USAGE(8, 0x31),
+					HID_RI_LOGICAL_MINIMUM(8, -2),
+					HID_RI_LOGICAL_MAXIMUM(8, 1),
+					HID_RI_REPORT_COUNT(8, 1),
+					HID_RI_REPORT_SIZE(8, 2),
+					HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+
+					HID_RI_REPORT_SIZE(8, 1),
+					HID_RI_REPORT_COUNT(8, 0x01),
+					HID_RI_INPUT(8, HID_IOF_CONSTANT),
+
+					HID_RI_USAGE(8, 0x30),
+					HID_RI_LOGICAL_MINIMUM(8, -2),
+					HID_RI_LOGICAL_MAXIMUM(8, 1),
+					HID_RI_REPORT_COUNT(8, 1),
+					HID_RI_REPORT_SIZE(8, 2),
+					HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+				HID_RI_END_COLLECTION(0),
+
+			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(1,1,0),
+	.Class                  = USB_CSCP_NoDeviceClass,
+	.SubClass               = USB_CSCP_NoDeviceSubclass,
+	.Protocol               = USB_CSCP_NoDeviceProtocol,
+
+	.Endpoint0Size          = FIXED_CONTROL_ENDPOINT_SIZE,
+
+	.VendorID               = 0x03EB,
+	.ProductID              = 0x2043,
+	.ReleaseNumber          = VERSION_BCD(0,0,1),
+
+	.ManufacturerStrIndex   = STRING_ID_Manufacturer,
+	.ProductStrIndex        = STRING_ID_Product,
+	.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        = 1,
+
+			.ConfigurationNumber    = 1,
+			.ConfigurationStrIndex  = NO_DESCRIPTOR,
+
+			.ConfigAttributes       = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_SELFPOWERED),
+
+			.MaxPowerConsumption    = USB_CONFIG_POWER_MA(100)
+		},
+
+	.HID_Interface =
+		{
+			.Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+			.InterfaceNumber        = INTERFACE_ID_Joystick,
+			.AlternateSetting       = 0x00,
+
+			.TotalEndpoints         = 1,
+
+			.Class                  = HID_CSCP_HIDClass,
+			.SubClass               = HID_CSCP_NonBootSubclass,
+			.Protocol               = HID_CSCP_NonBootProtocol,
+
+			.InterfaceStrIndex      = NO_DESCRIPTOR
+		},
+
+	.HID_JoystickHID =
+		{
+			.Header                 = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
+
+			.HIDSpec                = VERSION_BCD(1,1,1),
+			.CountryCode            = 0x00,
+			.TotalReportDescriptors = 1,
+			.HIDReportType          = HID_DTYPE_Report,
+			.HIDReportLength        = sizeof(JoystickReport)
+		},
+
+	.HID_ReportINEndpoint =
+		{
+			.Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+			.EndpointAddress        = JOYSTICK_EPADDR,
+			.Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+			.EndpointSize           = JOYSTICK_EPSIZE,
+			.PollingIntervalMS      = 0x05
+		}
+};
+
+/** 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 = USB_STRING_DESCRIPTOR_ARRAY(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 = USB_STRING_DESCRIPTOR(L"LUFA Library");
+
+/** 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 = USB_STRING_DESCRIPTOR(L"LUFA Joystick 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 uint16_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 STRING_ID_Language:
+					Address = &LanguageString;
+					Size    = pgm_read_byte(&LanguageString.Header.Size);
+					break;
+				case STRING_ID_Manufacturer:
+					Address = &ManufacturerString;
+					Size    = pgm_read_byte(&ManufacturerString.Header.Size);
+					break;
+				case STRING_ID_Product:
+					Address = &ProductString;
+					Size    = pgm_read_byte(&ProductString.Header.Size);
+					break;
+			}
+
+			break;
+		case HID_DTYPE_HID:
+			Address = &ConfigurationDescriptor.HID_JoystickHID;
+			Size    = sizeof(USB_HID_Descriptor_HID_t);
+			break;
+		case HID_DTYPE_Report:
+			Address = &JoystickReport;
+			Size    = sizeof(JoystickReport);
+			break;
+	}
+
+	*DescriptorAddress = Address;
+	return Size;
+}
+
Index: grip2hid/Descriptors.h
===================================================================
--- grip2hid/Descriptors.h	(revision 703832c006eb1d6b9c500dead75987968fae6928)
+++ grip2hid/Descriptors.h	(revision 703832c006eb1d6b9c500dead75987968fae6928)
@@ -0,0 +1,93 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2021.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2021  Dean Camera (dean [at] fourwalledcubicle [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 disclaims 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
+ *
+ *  Header file for Descriptors.c.
+ */
+
+#ifndef _DESCRIPTORS_H_
+#define _DESCRIPTORS_H_
+
+	/* Includes: */
+		#include <avr/pgmspace.h>
+
+		#include <LUFA/Drivers/USB/USB.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;
+
+			// Joystick HID Interface
+			USB_Descriptor_Interface_t            HID_Interface;
+			USB_HID_Descriptor_HID_t              HID_JoystickHID;
+	        USB_Descriptor_Endpoint_t             HID_ReportINEndpoint;
+		} USB_Descriptor_Configuration_t;
+
+		/** Enum for the device interface descriptor IDs within the device. Each interface descriptor
+		 *  should have a unique ID index associated with it, which can be used to refer to the
+		 *  interface from other descriptors.
+		 */
+		enum InterfaceDescriptors_t
+		{
+			INTERFACE_ID_Joystick = 0, /**< Joystick interface desciptor ID */
+		};
+
+		/** Enum for the device string descriptor IDs within the device. Each string descriptor should
+		 *  have a unique ID index associated with it, which can be used to refer to the string from
+		 *  other descriptors.
+		 */
+		enum StringDescriptors_t
+		{
+			STRING_ID_Language     = 0, /**< Supported Languages string descriptor ID (must be zero) */
+			STRING_ID_Manufacturer = 1, /**< Manufacturer string ID */
+			STRING_ID_Product      = 2, /**< Product string ID */
+		};
+
+	/* Macros: */
+		/** Endpoint address of the Joystick HID reporting IN endpoint. */
+		#define JOYSTICK_EPADDR              (ENDPOINT_DIR_IN | 1)
+
+		/** Size in bytes of the Joystick HID reporting IN endpoint. */
+		#define JOYSTICK_EPSIZE              8
+
+	/* Function Prototypes: */
+		uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+		                                    const uint16_t wIndex,
+		                                    const void** const DescriptorAddress)
+		                                    ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
+
+#endif
+
Index: grip2hid/Joystick.c
===================================================================
--- grip2hid/Joystick.c	(revision 703832c006eb1d6b9c500dead75987968fae6928)
+++ grip2hid/Joystick.c	(revision 703832c006eb1d6b9c500dead75987968fae6928)
@@ -0,0 +1,193 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2021.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2021  Dean Camera (dean [at] fourwalledcubicle [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 disclaims 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
+ *
+ *  Main source file for the Joystick demo. This file contains the main tasks of
+ *  the demo and is responsible for the initial application hardware configuration.
+ */
+
+#include "Joystick.h"
+
+extern void GrIP_Init();
+extern uint8_t GrIP_Read(uint32_t*, uint8_t);
+
+/** Buffer to hold the previously generated HID report, for comparison purposes inside the HID class driver. */
+static uint8_t PrevJoystickHIDReportBuffer[4];
+
+/** LUFA HID Class driver interface configuration and state information. This structure is
+ *  passed to all HID Class driver functions, so that multiple instances of the same class
+ *  within a device can be differentiated from one another.
+ */
+USB_ClassInfo_HID_Device_t Joystick_HID_Interface =
+	{
+		.Config =
+			{
+				.InterfaceNumber              = INTERFACE_ID_Joystick,
+				.ReportINEndpoint             =
+					{
+						.Address              = JOYSTICK_EPADDR,
+						.Size                 = JOYSTICK_EPSIZE,
+						.Banks                = 1,
+					},
+				.PrevReportINBuffer           = PrevJoystickHIDReportBuffer,
+				.PrevReportINBufferSize       = sizeof(PrevJoystickHIDReportBuffer),
+			},
+	};
+
+
+/** Main program entry point. This routine contains the overall program flow, including initial
+ *  setup of all components and the main program loop.
+ */
+int main(void)
+{
+	SetupHardware();
+
+	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+	GlobalInterruptEnable();
+
+	for (;;)
+	{
+		HID_Device_USBTask(&Joystick_HID_Interface);
+		USB_USBTask();
+	}
+}
+
+/** Configures the board hardware and chip peripherals for the demo's functionality. */
+void SetupHardware(void)
+{
+#if (ARCH == ARCH_AVR8)
+	/* Disable watchdog if enabled by bootloader/fuses */
+	MCUSR &= ~(1 << WDRF);
+	wdt_disable();
+
+	/* Disable clock division */
+	clock_prescale_set(clock_div_1);
+#elif (ARCH == ARCH_XMEGA)
+	/* Start the PLL to multiply the 2MHz RC oscillator to 32MHz and switch the CPU core to run from it */
+	XMEGACLK_StartPLL(CLOCK_SRC_INT_RC2MHZ, 2000000, F_CPU);
+	XMEGACLK_SetCPUClockSource(CLOCK_SRC_PLL);
+
+	/* Start the 32MHz internal RC oscillator and start the DFLL to increase it to 48MHz using the USB SOF as a reference */
+	XMEGACLK_StartInternalOscillator(CLOCK_SRC_INT_RC32MHZ);
+	XMEGACLK_StartDFLL(CLOCK_SRC_INT_RC32MHZ, DFLL_REF_INT_USBSOF, F_USB);
+
+	PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;
+#endif
+
+	/* Hardware Initialization */
+	GrIP_Init();
+	LEDs_Init();
+	Buttons_Init();
+	USB_Init();
+}
+
+/** Event handler for the library USB Connection event. */
+void EVENT_USB_Device_Connect(void)
+{
+	LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
+}
+
+/** Event handler for the library USB Disconnection event. */
+void EVENT_USB_Device_Disconnect(void)
+{
+	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+}
+
+/** Event handler for the library USB Configuration Changed event. */
+void EVENT_USB_Device_ConfigurationChanged(void)
+{
+	bool ConfigSuccess = true;
+
+	ConfigSuccess &= HID_Device_ConfigureEndpoints(&Joystick_HID_Interface);
+
+	USB_Device_EnableSOFEvents();
+
+	LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
+}
+
+/** Event handler for the library USB Control Request reception event. */
+void EVENT_USB_Device_ControlRequest(void)
+{
+	HID_Device_ProcessControlRequest(&Joystick_HID_Interface);
+}
+
+/** Event handler for the USB device Start Of Frame event. */
+void EVENT_USB_Device_StartOfFrame(void)
+{
+	HID_Device_MillisecondElapsed(&Joystick_HID_Interface);
+}
+
+/** HID class driver callback function for the creation of HID reports to the host.
+ *
+ *  \param[in]     HIDInterfaceInfo  Pointer to the HID class interface configuration structure being referenced
+ *  \param[in,out] ReportID    Report ID requested by the host if non-zero, otherwise callback should set to the generated report ID
+ *  \param[in]     ReportType  Type of the report to create, either HID_REPORT_ITEM_In or HID_REPORT_ITEM_Feature
+ *  \param[out]    ReportData  Pointer to a buffer where the created report should be stored
+ *  \param[out]    ReportSize  Number of bytes written in the report (or zero if no report is to be sent)
+ *
+ *  \return Boolean \c true to force the sending of the report, \c false to let the library determine if it needs to be sent
+ */
+bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
+                                         uint8_t* const ReportID,
+                                         const uint8_t ReportType,
+                                         void* ReportData,
+                                         uint16_t* const ReportSize)
+{
+	*ReportID = GrIP_Read(ReportData, *ReportID) + 1;
+
+	// Flip the up/down axis in the right direction for USB reports
+	uint8_t* data = (uint8_t*)ReportData;
+	uint8_t up = data[3] & 0x08;
+	uint8_t down = data[3] & 0x10;
+	data[3] ^= up | down;
+	data[3] ^= (up << 1) | (down >> 1);
+
+	*ReportSize = 4;
+	return true;
+}
+
+/** HID class driver callback function for the processing of HID reports from the host.
+ *
+ *  \param[in] HIDInterfaceInfo  Pointer to the HID class interface configuration structure being referenced
+ *  \param[in] ReportID    Report ID of the received report from the host
+ *  \param[in] ReportType  The type of report that the host has sent, either HID_REPORT_ITEM_Out or HID_REPORT_ITEM_Feature
+ *  \param[in] ReportData  Pointer to a buffer where the received report has been stored
+ *  \param[in] ReportSize  Size in bytes of the received HID report
+ */
+void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
+                                          const uint8_t ReportID,
+                                          const uint8_t ReportType,
+                                          const void* ReportData,
+                                          const uint16_t ReportSize)
+{
+	// Unused (but mandatory for the HID class driver) in this demo, since there are no Host->Device reports
+}
+
Index: grip2hid/Joystick.h
===================================================================
--- grip2hid/Joystick.h	(revision 703832c006eb1d6b9c500dead75987968fae6928)
+++ grip2hid/Joystick.h	(revision 703832c006eb1d6b9c500dead75987968fae6928)
@@ -0,0 +1,89 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2021.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2021  Dean Camera (dean [at] fourwalledcubicle [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 disclaims 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
+ *
+ *  Header file for Joystick.c.
+ */
+
+#ifndef _JOYSTICK_H_
+#define _JOYSTICK_H_
+
+	/* Includes: */
+		#include <avr/io.h>
+		#include <avr/wdt.h>
+		#include <avr/power.h>
+		#include <avr/interrupt.h>
+		#include <string.h>
+
+		#include "Descriptors.h"
+
+		#include <LUFA/Drivers/Board/Joystick.h>
+		#include <LUFA/Drivers/Board/LEDs.h>
+		#include <LUFA/Drivers/Board/Buttons.h>
+		#include <LUFA/Drivers/USB/USB.h>
+		#include <LUFA/Platform/Platform.h>
+
+	/* Type Defines: */
+	/* Macros: */
+		/** LED mask for the library LED driver, to indicate that the USB interface is not ready. */
+		#define LEDMASK_USB_NOTREADY      LEDS_LED1
+
+		/** LED mask for the library LED driver, to indicate that the USB interface is enumerating. */
+		#define LEDMASK_USB_ENUMERATING  (LEDS_LED2 | LEDS_LED3)
+
+		/** LED mask for the library LED driver, to indicate that the USB interface is ready. */
+		#define LEDMASK_USB_READY        (LEDS_LED2 | LEDS_LED4)
+
+		/** LED mask for the library LED driver, to indicate that an error has occurred in the USB interface. */
+		#define LEDMASK_USB_ERROR        (LEDS_LED1 | LEDS_LED3)
+
+	/* Function Prototypes: */
+		void SetupHardware(void);
+
+		void EVENT_USB_Device_Connect(void);
+		void EVENT_USB_Device_Disconnect(void);
+		void EVENT_USB_Device_ConfigurationChanged(void);
+		void EVENT_USB_Device_ControlRequest(void);
+		void EVENT_USB_Device_StartOfFrame(void);
+
+		bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
+		                                         uint8_t* const ReportID,
+		                                         const uint8_t ReportType,
+		                                         void* ReportData,
+		                                         uint16_t* const ReportSize);
+		void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
+		                                          const uint8_t ReportID,
+		                                          const uint8_t ReportType,
+		                                          const void* ReportData,
+		                                          const uint16_t ReportSize);
+
+#endif
+
Index: ip2hid/Makefile
===================================================================
--- grip2hid/Makefile	(revision 81b8d53252336fbeb95d0faaf51d9fbb7100ef27)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#Set vars
-PROJECT=grip2hid
-FCPU=1000000
-BAUD=9600
-
-PROG=flip1 -u
-MCU=at90usb1287
-
-#MCU=atmega8
-#PROG=avr109 -P /dev/ports/usb0 -b $(BAUD) -u
-
-# You should not need to change anything below
-# -----------------------------------------------------------------------------
-COMPILE = avr-g++ -Wall -Wextra -Werror -O3 -mmcu=$(MCU) -DF_CPU=$(FCPU) -DBAUD=$(BAUD)
-
-#Rules
-$(PROJECT).hex: $(PROJECT).bin
-	avr-objcopy -j .text -j .data -O ihex $^ $@
-
-$(PROJECT).bin: main.o usart.o
-	$(COMPILE) $^ -o $@
-
-#Generic rules
-.S.o:
-	$(COMPILE) -x assembler-with-cpp -c $< -o $@
-
-.cpp.o:
-	$(COMPILE) -c $< -o $@
-
-usart.o: ../libs/usart/usart.c
-	$(COMPILE) -c $< -o $@
-
-flash: $(PROJECT).hex
-	avrdude -u -c $(PROG) -p $(MCU) -Uflash:w:$^
-
-clean:
-	rm *.bin *.hex *.o
Index: grip2hid/README.md
===================================================================
--- grip2hid/README.md	(revision 81b8d53252336fbeb95d0faaf51d9fbb7100ef27)
+++ grip2hid/README.md	(revision 703832c006eb1d6b9c500dead75987968fae6928)
@@ -11,8 +11,17 @@
 (2 gameports, each allowing to use 2 gamepads thanks to Gravis chaining system).
 
+The gamepads are each reported as a separate USB report, and show up as 4 independant
+gamepads on both Windows and Haiku. Buttons are assigned in this order:
+green, yellow, red, blue, L1, R1, start, select, R2, L2. This order is reasonable
+(but not perfect) while allowing to reuse the bits received from the gamepad almost
+directly to fill the HID report. The only change needed is inverting the Y axis,
+because USB wants the up direction to be lowest values.
+
 It is powered by an AT90USB AVR microcontroller, because these implement USB in
-hardware and have easily usable external interupts (PCINT) making it much easier
-to implement the protocol (this helps because the gamepad is the master and
-drives the clock).
+hardware and make it easy to implement an HID device.
+
+You need the LUFA USB stack to compile this project. I am not including it to
+avoid code duplication. Download and extract it yourself, or set the LUFA_PATH variable
+to where you already have it when compiling.
 
 [Further reading on GrIP](http://pulkomandy.tk/_/_Electronique/_Gravis%20Interface%20Protocol)
Index: grip2hid/grip.cpp
===================================================================
--- grip2hid/grip.cpp	(revision 703832c006eb1d6b9c500dead75987968fae6928)
+++ grip2hid/grip.cpp	(revision 703832c006eb1d6b9c500dead75987968fae6928)
@@ -0,0 +1,169 @@
+#include <avr/io.h>
+
+#include <stdbool.h>
+
+// The UART is on PD2 (Rx) and PD3 (Tx)
+// The gamepads are all connected on port B
+#define GRIP_PORT PORTB
+#define GRIP_DDR  DDRB
+#define GRIP_PIN  PINB
+#define GRIP_DAT_A  (1 << 0)
+#define GRIP_CLK_A  (1 << 1)
+#define GRIP_DAT_B  (1 << 3)
+#define GRIP_CLK_B  (1 << 2)
+#define GRIP_DAT_C  (1 << 7)
+#define GRIP_CLK_C  (1 << 6)
+#define GRIP_DAT_D  (1 << 5)
+#define GRIP_CLK_D  (1 << 4)
+
+class GrIP
+{
+public:
+	GrIP()
+	{
+		word = 0;
+		count = 0;
+		state = 0;
+	}
+
+	// Push the next bit and returns true if it completes a word.
+	// The whole 24 bit word is stored in "word" and consists of:
+	// - One 7-bit sync pattern: always 0111111
+	// - Three 6-bit blocks starting with a 0 followed by 5 button bits
+	bool PushBit(uint32_t bit)
+	{
+		word = (word >> 1) | ((bit & 1) << 31);
+		count++;
+
+		switch (state) {
+			case 0:
+				if ((word & 0xFE000000) != 0x7C000000) return false;
+				count = 7;
+				state = 1;
+				break;
+			case 1:
+				if (count == 24) {
+					state = 0;
+					count = 0;
+					return true;
+				}
+				break;
+		}
+
+		return false;
+	}
+
+public:
+	uint32_t word;
+private:
+	uint8_t count;
+	uint8_t state; // 0 = looking for sync, 1 = synchronized (we received 0111111)
+};
+
+
+extern "C" void GrIP_Init() {
+	// GrIP input
+	GRIP_PORT = 0xFF; // Enable pull-ups
+	GRIP_DDR = 0;  // Port as input
+}
+
+extern "C" uint8_t GrIP_Read(uint32_t* v, uint8_t k2) {
+	// Initial value of oldv for edge detection
+	uint8_t oldv = GRIP_PIN;
+	static uint8_t k = 0;
+	if (k2 != 0)
+		k = k2 - 1;
+	else {
+		k++; if (k > 3) k = 0;
+	}
+
+		// Because the CPU is too slow, if we try to scan all pads at once we
+		// don't manage to decode them (missed transitions). So we scan them
+		// one at a time.
+		// To scan all 4 gamepads this will take about 4 milliseconds, which
+		// is not the best we could do, but is okay. When we have the real
+		// hardware (with the CPU running at full 16MHz speed instead of crappy
+		// 1MHz here), we can try to interleave them again (one just has to put
+		// them all into a single for loop instead of separate loops for each).
+		// Then we get to 1ms to scan all 4 pads in parallel, cool! And it
+		// also fixes the problem mentionned below that when less pads are
+		// connected, it will not slowdown waiting for one of them to timeout.
+		//
+		// When a gamepad is plugged, the loop seems to complete in around 1000 iterations.
+		// When no gamepad is plugged, that's a timeout.
+
+		// Process pad1
+		GrIP pad;
+		uint16_t i;
+
+		if (k == 0)
+		for (i = 0; i < 2048; i++) {
+			uint8_t newv = GRIP_PIN;
+			if (!(newv & GRIP_CLK_A)) { // clock is down
+				if (oldv & GRIP_CLK_A) { // and it was up at previous read
+					// Read bit
+					uint32_t bit = (newv & GRIP_DAT_A) != 0;
+					if (pad.PushBit(bit)) {
+						*v = pad.word;
+						break;
+					}
+				}
+			}
+			oldv = newv;
+		}
+
+		// Process pad 2
+		if (k == 1)
+		for (i = 0; i < 2048; i++) {
+			uint8_t newv = GRIP_PIN;
+			if (!(newv & GRIP_CLK_B)) { // clock is down
+				if (oldv & GRIP_CLK_B) { // and it was up at previous read
+					// Read bit
+					uint32_t bit = (newv & GRIP_DAT_B) != 0;
+					if (pad.PushBit(bit)) {
+						*v = pad.word;
+						break;
+					}
+				}
+			}
+			oldv = newv;
+		}
+
+		// Process pad 3
+		if (k == 2)
+		for (i = 0; i < 2048; i++) {
+			uint8_t newv = GRIP_PIN;
+			if (!(newv & GRIP_CLK_C)) { // clock is down
+				if (oldv & GRIP_CLK_C) { // and it was up at previous read
+					// Read bit
+					uint32_t bit = (newv & GRIP_DAT_C) != 0;
+					if (pad.PushBit(bit)) {
+						*v = pad.word;
+						break;
+					}
+				}
+			}
+			oldv = newv;
+		}
+
+		// Process pad 4
+		if (k == 3)
+		for (i = 0; i < 2048; i++) {
+			uint8_t newv = GRIP_PIN;
+			if (!(newv & GRIP_CLK_D)) { // clock is down
+				if (oldv & GRIP_CLK_D) { // and it was up at previous read
+					// Read bit
+					uint32_t bit = (newv & GRIP_DAT_D) != 0;
+					if (pad.PushBit(bit)) {
+						*v = pad.word;
+						break;
+					}
+				}
+			}
+			oldv = newv;
+		}
+
+		return k;
+}
+
+
Index: ip2hid/main.cpp
===================================================================
--- grip2hid/main.cpp	(revision 81b8d53252336fbeb95d0faaf51d9fbb7100ef27)
+++ 	(revision )
@@ -1,188 +1,0 @@
-#include <avr/io.h>
-#include <avr/interrupt.h>
-#include <avr/wdt.h>
-#include <avr/pgmspace.h>
-#include <util/delay.h>
-
-#include <string.h>
-#include <stdbool.h>
-
-#include "../libs/usart/usart.h"
-
-#define GRIP_PORT PORTB
-#define GRIP_DDR  DDRB
-#define GRIP_PIN  PINB
-#define GRIP_DAT_A  (1 << 0)
-#define GRIP_CLK_A  (1 << 1)
-#define GRIP_DAT_B  (1 << 3)
-#define GRIP_CLK_B  (1 << 2)
-#define GRIP_DAT_C  (1 << 7)
-#define GRIP_CLK_C  (1 << 6)
-#define GRIP_DAT_D  (1 << 5)
-#define GRIP_CLK_D  (1 << 4)
-
-class GrIP
-{
-public:
-	GrIP()
-	{
-		word = 0;
-		count = 0;
-		state = 0;
-	}
-
-	bool PushBit(uint32_t bit)
-	{
-		word = (word << 1) | (bit & 1);
-		count++;
-
-		switch (state) {
-			case 0:
-				if ((word & 0x3F) != 0x1F) return false;
-				count = 6;
-				state = 1;
-				break;
-			case 1:
-				if (count == 24) {
-					state = 0;
-					count = 0;
-					return true;
-				}
-				break;
-		}
-
-		return false;
-	}
-
-	void Dump() {
-		USARTWriteHex(word >> 16);
-		USARTWriteHex(word >> 8);
-		USARTWriteHex(word);
-	}
-
-private:
-	uint32_t word;
-	uint8_t count;
-	uint8_t state;
-};
-
-
-int main() {
-	wdt_enable(WDTO_2S);
-
-	// GrIP input
-	GRIP_PORT = 0xFF; // Enable pull-ups
-	GRIP_DDR = 0;  // Port as input
-
-	USARTInit();
-	USARTWriteChar('h');
-	USARTWriteChar('\r');
-	USARTWriteChar('\n');
-
-	// Initial value of oldv for edge detection
-	uint8_t oldv = GRIP_PIN;
-
-	for (;;) {
-		// Because the CPU is too slow, if we try to scan all pads at once we
-		// don't manage to decode them (missed transitions). So we scan them
-		// one at a time.
-		// To scan all 4 gamepads this will take about 4 milliseconds, which
-		// is not the best we could do, but is okay. When we have the real
-		// hardware (with the CPU running at full 16MHz speed instead of crappy
-		// 1MHz here), we can try to interleave them again (one just has to put
-		// them all into a single for loop instead of separate loops for each).
-		// Then we get to 1ms to scan all 4 pads in parallel, cool! And it
-		// also fixes the problem mentionned below that when less pads are
-		// connected, it will not slowdown waiting for one of them to timeout.
-
-		// FIXME the loop to 255 here to wait for a bit isn't too nice. We
-		// should rather use a timer with a known period?
-		// Process pad1
-		GrIP pad;
-		uint8_t i;
-		for (i = 0; i < 255; i++) {
-			wdt_reset();
-
-			uint8_t newv = GRIP_PIN;
-
-			if (!(newv & GRIP_CLK_A)) { // clock is down
-				if (oldv & GRIP_CLK_A) { // and it was up at previous read
-					// Read bit
-					uint32_t bit = (newv & GRIP_DAT_A) != 0;
-					if (pad.PushBit(bit)) {
-						break;
-					}
-				}
-			}
-			oldv = newv;
-		}
-
-		pad.Dump();
-		USARTWriteChar(' ');
-
-		// Process pad 2
-		for (i = 0; i < 255; i++) {
-			wdt_reset();
-
-			uint8_t newv = GRIP_PIN;
-			if (!(newv & GRIP_CLK_B)) { // clock is down
-				if (oldv & GRIP_CLK_B) { // and it was up at previous read
-					// Read bit
-					uint32_t bit = (newv & GRIP_DAT_B) != 0;
-					if (pad.PushBit(bit)) {
-						break;
-					}
-				}
-			}
-			oldv = newv;
-		}
-
-		pad.Dump();
-		USARTWriteChar(' ');
-
-		// Process pad 3
-		for (i = 0; i < 255; i++) {
-			wdt_reset();
-
-			uint8_t newv = GRIP_PIN;
-			if (!(newv & GRIP_CLK_C)) { // clock is down
-				if (oldv & GRIP_CLK_C) { // and it was up at previous read
-					// Read bit
-					uint32_t bit = (newv & GRIP_DAT_C) != 0;
-					if (pad.PushBit(bit)) {
-						break;
-					}
-				}
-			}
-			oldv = newv;
-		}
-
-		pad.Dump();
-		USARTWriteChar(' ');
-
-		// Process pad 4
-		for (i = 0; i < 255; i++) {
-			wdt_reset();
-
-			uint8_t newv = GRIP_PIN;
-			if (!(newv & GRIP_CLK_D)) { // clock is down
-				if (oldv & GRIP_CLK_D) { // and it was up at previous read
-					// Read bit
-					uint32_t bit = (newv & GRIP_DAT_D) != 0;
-					if (pad.PushBit(bit)) {
-						break;
-					}
-				}
-			}
-			oldv = newv;
-		}
-
-		pad.Dump();
-		USARTWriteChar('\r');
-		USARTWriteChar('\n');
-	}
-
-	return 0;
-}
-
-
Index: grip2hid/makefile
===================================================================
--- grip2hid/makefile	(revision 703832c006eb1d6b9c500dead75987968fae6928)
+++ grip2hid/makefile	(revision 703832c006eb1d6b9c500dead75987968fae6928)
@@ -0,0 +1,48 @@
+#
+#             LUFA Library
+#     Copyright (C) Dean Camera, 2021.
+#
+#  dean [at] fourwalledcubicle [dot] com
+#           www.lufa-lib.org
+#
+# --------------------------------------
+#         LUFA Project Makefile.
+# --------------------------------------
+
+# Run "make help" for target help.
+
+MCU          = at90usb1287
+ARCH         = AVR8
+BOARD        = USBKEY
+F_CPU        = 8000000
+F_USB        = $(F_CPU)
+OPTIMIZATION = s
+TARGET       = Joystick
+SRC          = $(TARGET).c Descriptors.c grip.cpp $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS)
+LUFA_PATH    ?= lufa-LUFA-210130/LUFA
+CC_FLAGS     = -DUSE_LUFA_CONFIG_HEADER -IConfig/
+LD_FLAGS     =
+
+# Default target
+all:
+
+# Include LUFA-specific DMBS extension modules
+DMBS_LUFA_PATH ?= $(LUFA_PATH)/Build/LUFA
+include $(DMBS_LUFA_PATH)/lufa-sources.mk
+include $(DMBS_LUFA_PATH)/lufa-gcc.mk
+
+# Include common DMBS build system modules
+DMBS_PATH      ?= $(LUFA_PATH)/Build/DMBS/DMBS
+include $(DMBS_PATH)/core.mk
+include $(DMBS_PATH)/cppcheck.mk
+include $(DMBS_PATH)/doxygen.mk
+include $(DMBS_PATH)/dfu.mk
+include $(DMBS_PATH)/gcc.mk
+include $(DMBS_PATH)/hid.mk
+include $(DMBS_PATH)/avrdude.mk
+include $(DMBS_PATH)/atprogram.mk
+
+PROG=avr109 -P /dev/ports/usb0
+flash: $(TARGET).hex
+	avrdude -u -c $(PROG) -p $(MCU) -Uflash:w:$^
+
