From 60b30c036397cb5627fa374bb930794b225daa29 Mon Sep 17 00:00:00 2001
From: Jack Humbert <jack.humb@gmail.com>
Date: Fri, 7 Jul 2017 11:55:23 -0400
Subject: Squashed 'lib/lufa/' content from commit 385d40300

git-subtree-dir: lib/lufa
git-subtree-split: 385d4030035dbaf41591309dbde47653bd03841b
---
 Projects/Magstripe/Config/AppConfig.h      |   58 +
 Projects/Magstripe/Config/LUFAConfig.h     |   93 ++
 Projects/Magstripe/Descriptors.c           |  216 +++
 Projects/Magstripe/Descriptors.h           |   96 ++
 Projects/Magstripe/Lib/CircularBitBuffer.c |  115 ++
 Projects/Magstripe/Lib/CircularBitBuffer.h |   97 ++
 Projects/Magstripe/Lib/MagstripeHW.h       |  102 ++
 Projects/Magstripe/Magstripe.c             |  228 +++
 Projects/Magstripe/Magstripe.h             |   90 ++
 Projects/Magstripe/Magstripe.txt           |  163 ++
 Projects/Magstripe/asf.xml                 |   52 +
 Projects/Magstripe/doxyfile                | 2395 ++++++++++++++++++++++++++++
 Projects/Magstripe/makefile                |   43 +
 13 files changed, 3748 insertions(+)
 create mode 100644 Projects/Magstripe/Config/AppConfig.h
 create mode 100644 Projects/Magstripe/Config/LUFAConfig.h
 create mode 100644 Projects/Magstripe/Descriptors.c
 create mode 100644 Projects/Magstripe/Descriptors.h
 create mode 100644 Projects/Magstripe/Lib/CircularBitBuffer.c
 create mode 100644 Projects/Magstripe/Lib/CircularBitBuffer.h
 create mode 100644 Projects/Magstripe/Lib/MagstripeHW.h
 create mode 100644 Projects/Magstripe/Magstripe.c
 create mode 100644 Projects/Magstripe/Magstripe.h
 create mode 100644 Projects/Magstripe/Magstripe.txt
 create mode 100644 Projects/Magstripe/asf.xml
 create mode 100644 Projects/Magstripe/doxyfile
 create mode 100644 Projects/Magstripe/makefile

(limited to 'Projects/Magstripe')

diff --git a/Projects/Magstripe/Config/AppConfig.h b/Projects/Magstripe/Config/AppConfig.h
new file mode 100644
index 0000000000..2b417b8a90
--- /dev/null
+++ b/Projects/Magstripe/Config/AppConfig.h
@@ -0,0 +1,58 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2017.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2017  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 Application Configuration Header File
+ *
+ *  This is a header file which is be used to configure some of
+ *  the application's compile time options, as an alternative to
+ *  specifying the compile time constants supplied through a
+ *  makefile or build system.
+ *
+ *  For information on what each token does, refer to the
+ *  \ref Sec_Options section of the application documentation.
+ */
+
+#ifndef _APP_CONFIG_H_
+#define _APP_CONFIG_H_
+
+	#define MAG_T1_CLOCK         (1 << 0)
+	#define MAG_T1_DATA          (1 << 1)
+	#define MAG_T2_CLOCK         (1 << 2)
+	#define MAG_T2_DATA          (1 << 3)
+	#define MAG_T3_CLOCK         (1 << 4)
+	#define MAG_T3_DATA          (1 << 5)
+	#define MAG_CARDPRESENT      (1 << 6)
+
+	#define MAG_PORT             PORTC
+	#define MAG_PIN              PINC
+	#define MAG_DDR              DDRC
+
+#endif
diff --git a/Projects/Magstripe/Config/LUFAConfig.h b/Projects/Magstripe/Config/LUFAConfig.h
new file mode 100644
index 0000000000..2b8d027a3d
--- /dev/null
+++ b/Projects/Magstripe/Config/LUFAConfig.h
@@ -0,0 +1,93 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2017.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2017  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            0
+		#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
+
+	#else
+
+		#error Unsupported architecture for this LUFA configuration file.
+
+	#endif
+#endif
diff --git a/Projects/Magstripe/Descriptors.c b/Projects/Magstripe/Descriptors.c
new file mode 100644
index 0000000000..8032bccc84
--- /dev/null
+++ b/Projects/Magstripe/Descriptors.c
@@ -0,0 +1,216 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2017.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2010  Denver Gingerich (denver [at] ossguy [dot] com)
+  Copyright 2017  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 report descriptor. This is a HID class specific descriptor, which defines the structure of the
+ *  reports sent and received by the HID device to and from the USB host. It indicates what data is sent,
+ *  where in the report each element is located and exactly how the data should be interpreted and used.
+ *
+ *  See the HID class specification for more information on HID report descriptors.
+ */
+const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
+{
+	/* Use the HID class driver's standard Keyboard report.
+	 *   Max simultaneous keys: 6
+	 */
+	HID_DESCRIPTOR_KEYBOARD(6)
+};
+
+/** 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              = 0x2042,
+	.ReleaseNumber          = VERSION_BCD(0,0,1),
+
+	.ManufacturerStrIndex   = STRING_ID_Manufacturer,
+	.ProductStrIndex        = STRING_ID_Product,
+	.SerialNumStrIndex      = USE_INTERNAL_SERIAL,
+
+	.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_Keyboard,
+			.AlternateSetting       = 0x00,
+
+			.TotalEndpoints         = 1,
+
+			.Class                  = HID_CSCP_HIDClass,
+			.SubClass               = HID_CSCP_BootSubclass,
+			.Protocol               = HID_CSCP_KeyboardBootProtocol,
+
+			.InterfaceStrIndex      = NO_DESCRIPTOR
+		},
+
+	.HID_KeyboardHID =
+		{
+			.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(KeyboardReport)
+		},
+
+	.HID_ReportINEndpoint =
+		{
+			.Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+			.EndpointAddress        = KEYBOARD_EPADDR,
+			.Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+			.EndpointSize           = KEYBOARD_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"Dean Camera and Denver Gingerich");
+
+/** 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"Magnetic Card Reader");
+
+/** 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_KeyboardHID;
+			Size    = sizeof(USB_HID_Descriptor_HID_t);
+			break;
+		case HID_DTYPE_Report:
+			Address = &KeyboardReport;
+			Size    = sizeof(KeyboardReport);
+			break;
+	}
+
+	*DescriptorAddress = Address;
+	return Size;
+}
+
diff --git a/Projects/Magstripe/Descriptors.h b/Projects/Magstripe/Descriptors.h
new file mode 100644
index 0000000000..149fe75314
--- /dev/null
+++ b/Projects/Magstripe/Descriptors.h
@@ -0,0 +1,96 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2017.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2010  Denver Gingerich (denver [at] ossguy [dot] com)
+  Copyright 2017  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>
+
+		#include "Config/AppConfig.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; /**< Configuration descriptor header structure */
+
+			// Keyboard HID Interface
+			USB_Descriptor_Interface_t            HID_Interface; /**< Keyboard interface descriptor */
+			USB_HID_Descriptor_HID_t              HID_KeyboardHID; /**< Keyboard HID descriptor */
+			USB_Descriptor_Endpoint_t             HID_ReportINEndpoint; /**< Keyboard key report endpoint descriptor */
+		} 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_Keyboard = 0, /**< Keyboard interface descriptor 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 keyboard key press reporting endpoint. */
+		#define KEYBOARD_EPADDR              (ENDPOINT_DIR_IN | 1)
+
+		/** Size of the keyboard report endpoints, in bytes. */
+		#define KEYBOARD_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
+
diff --git a/Projects/Magstripe/Lib/CircularBitBuffer.c b/Projects/Magstripe/Lib/CircularBitBuffer.c
new file mode 100644
index 0000000000..802d040c5b
--- /dev/null
+++ b/Projects/Magstripe/Lib/CircularBitBuffer.c
@@ -0,0 +1,115 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2017.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2010  Denver Gingerich (denver [at] ossguy [dot] com)
+  Copyright 2017  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.
+*/
+
+/** Circular bit buffer library. This will allow for individual bits
+ *  to be stored in packed form inside circular buffers, to reduce
+ *  overall RAM usage.
+ */
+
+#include "CircularBitBuffer.h"
+
+/** Function to initialize or reset a bit buffer, ready for data to be stored into it. */
+void BitBuffer_Init(BitBuffer_t* const Buffer)
+{
+	/* Reset the number of stored bits in the buffer */
+	Buffer->Elements        = 0;
+
+	/* Reset the data in and out pointer structures in the buffer to the first buffer bit */
+	Buffer->In.CurrentByte  = Buffer->Data;
+	Buffer->In.ByteMask     = (1 << 0);
+	Buffer->Out.CurrentByte = Buffer->Data;
+	Buffer->Out.ByteMask    = (1 << 0);
+}
+
+/** Function to store the given bit into the given bit buffer. */
+void BitBuffer_StoreNextBit(BitBuffer_t* const Buffer,
+                            const bool Bit)
+{
+	/* If the bit to store is true, set the next bit in the buffer */
+	if (Bit)
+	  *Buffer->In.CurrentByte |= Buffer->In.ByteMask;
+
+	/* Increment the number of stored bits in the buffer counter */
+	Buffer->Elements++;
+
+	/* Check if the current buffer byte is full of stored bits */
+	if (Buffer->In.ByteMask == (1 << 7))
+	{
+		/* Check if the end of the buffer has been reached, if so reset to start of buffer, otherwise advance to next bit */
+		if (Buffer->In.CurrentByte != &Buffer->Data[sizeof(Buffer->Data) - 1])
+		  Buffer->In.CurrentByte++;
+		else
+		  Buffer->In.CurrentByte = Buffer->Data;
+
+		/* Reset the storage bit mask in the current buffer byte to the first bit */
+		Buffer->In.ByteMask = (1 << 0);
+	}
+	else
+	{
+		/* Shift the current storage bit mask to the next bit in the current byte */
+		Buffer->In.ByteMask <<= 1;
+	}
+}
+
+/** Function to retrieve the next bit stored in the given bit buffer. */
+bool BitBuffer_GetNextBit(BitBuffer_t* const Buffer)
+{
+	/* Retrieve the value of the next bit stored in the buffer */
+	bool Bit = ((*Buffer->Out.CurrentByte & Buffer->Out.ByteMask) != 0);
+
+	/* Clear the buffer bit */
+	*Buffer->Out.CurrentByte &= ~Buffer->Out.ByteMask;
+
+	/* Decrement the number of stored bits in the buffer counter */
+	Buffer->Elements--;
+
+	/* Check if the current buffer byte is empty of stored bits */
+	if (Buffer->Out.ByteMask == (1 << 7))
+	{
+		/* Check if the end of the buffer has been reached, if so reset to start of buffer, otherwise advance to next bit */
+		if (Buffer->Out.CurrentByte != &Buffer->Data[sizeof(Buffer->Data) - 1])
+		  Buffer->Out.CurrentByte++;
+		else
+		  Buffer->Out.CurrentByte = Buffer->Data;
+
+		/* Reset the retrieval bit mask in the current buffer byte to the first bit */
+		Buffer->Out.ByteMask = (1 << 0);
+	}
+	else
+	{
+		/* Shift the current retrieval bit mask to the next bit in the current byte */
+		Buffer->Out.ByteMask <<= 1;
+	}
+
+	/* Return the retrieved bit from the buffer */
+	return Bit;
+}
+
diff --git a/Projects/Magstripe/Lib/CircularBitBuffer.h b/Projects/Magstripe/Lib/CircularBitBuffer.h
new file mode 100644
index 0000000000..0adbe0c89e
--- /dev/null
+++ b/Projects/Magstripe/Lib/CircularBitBuffer.h
@@ -0,0 +1,97 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2017.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2010  Denver Gingerich (denver [at] ossguy [dot] com)
+  Copyright 2017  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 CircularBitBuffer.c.
+ */
+
+#ifndef _CIRCULARBITBUFFER_H_
+#define _CIRCULARBITBUFFER_H_
+
+	/* Includes: */
+		#include <avr/io.h>
+		#include <stdbool.h>
+
+		#include <LUFA/Common/Common.h>
+
+	/* Macros: */
+		#if (defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB647__) || \
+		     defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__)) || defined(__DOXYGEN__)
+			/** Maximum number of bits which can be stored into a bit buffer. The memory usage is one eighth of this value per buffer. */
+			#define MAX_BITS 8192
+		#else
+			#define MAX_BITS 1024
+		#endif
+
+	/* Type Defines: */
+		/** Type define for a pointer to a bit in a bit buffer. */
+		typedef struct
+		{
+			uint8_t* CurrentByte; /**< Pointer to the current byte in the buffer */
+			uint8_t  ByteMask; /**< Mask of the current bit in the buffer */
+		} BitBufferPointer_t;
+
+		/** Type define for a circular packet bit buffer. */
+		typedef struct
+		{
+			uint8_t            Data[MAX_BITS / 8]; /**< Buffer to hold the stored bits in packed form */
+			uint16_t           Elements; /**< Number of stored bits in the bit buffer */
+
+			BitBufferPointer_t In; /**< Bit pointer to the next storage location in the buffer */
+			BitBufferPointer_t Out; /**< Bit pointer to the next retrieval location in the buffer */
+		} BitBuffer_t;
+
+	/* Function Prototypes: */
+		/** Initializes or resets a given bit buffer, ready to store new bits.
+		 *
+		 *  \param[in,out] Buffer  Bit buffer to initialize
+		 */
+		void BitBuffer_Init(BitBuffer_t* const Buffer) ATTR_NON_NULL_PTR_ARG(1);
+
+		/** Stores a bit into the next location inside a given bit buffer.
+		 *
+		 *  \param[in,out] Buffer  Bit buffer to store a bit into
+		 *  \param[in] Bit  Bit to store into the buffer
+		 */
+		void BitBuffer_StoreNextBit(BitBuffer_t* const Buffer,
+		                            const bool Bit) ATTR_NON_NULL_PTR_ARG(1);
+
+		/** Retrieves a bit from the next location inside a given bit buffer.
+		 *
+		 *  \param[in,out] Buffer  Bit buffer to retrieve a bit from
+		 *
+		 *  \return Next bit from the buffer
+		 */
+		bool BitBuffer_GetNextBit(BitBuffer_t* const Buffer) ATTR_NON_NULL_PTR_ARG(1);
+
+#endif
+
diff --git a/Projects/Magstripe/Lib/MagstripeHW.h b/Projects/Magstripe/Lib/MagstripeHW.h
new file mode 100644
index 0000000000..6d9cc8cbc4
--- /dev/null
+++ b/Projects/Magstripe/Lib/MagstripeHW.h
@@ -0,0 +1,102 @@
+/*
+  Copyright 2010  Denver Gingerich (denver [at] ossguy [dot] com)
+  Copyright 2017  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.
+*/
+
+/*
+	NOTE: The user of this include file MUST define the following macros
+	prior to including the file:
+
+	MAG_T1_CLOCK_PIN   Pin connected to Track 1 clock wire (i.e.. PORTC1)
+	MAG_T1_DATA_PIN    Pin connected to Track 1 data wire (i.e.. PORTC2)
+	MAG_T2_CLOCK_PIN   Pin connected to Track 2 clock wire (i.e.. PORTC3)
+	MAG_T2_DATA_PIN    Pin connected to Track 2 data wire (i.e.. PORTC0)
+	MAG_T3_CLOCK_PIN   Pin connected to Track 3 clock wire (i.e.. PORTC5)
+	MAG_T3_DATA_PIN    Pin connected to Track 3 data wire (i.e.. PORTC6)
+	MAG_CLS_PIN        Pin connected to card loaded wire (i.e.. PORTC4)
+	MAG_PIN            PIN macro for the reader's port (i.e.. PINC)
+	MAG_DDR            DDR macro for the reader's port (i.e.. DDRC)
+	MAG_PORT           PORT macro for the reader's port (i.e.. PORTC)
+
+	The example macros listed above assume that the Track 2 data wire is
+	connected to pin 0 on port C, the Track 2 clock wire is connected to
+	pin 3 on port C (similarly for Tracks 1 and 3), and the card loaded
+	wire is connected to pin 4 on port C.
+
+	If the mag-stripe reader you are using only reads one or two tracks,
+	then set the clock and data pins for the tracks it doesn't read to a
+	pin that is unused.  For example, on the AT90USBKey, any of the pins on
+	port C that do not have wires attached will be unused since they are
+	not connected to any onboard devices (such as the joystick or
+	temperature sensor).
+
+	Connecting wires to pins on different ports (i.e.. a data wire to pin 0
+	on port C and a clock wire to pin 0 on port D) is currently
+	unsupported.  All pins specified above must be on the same port.
+*/
+
+/** \file
+ *
+ *  Driver header for a TTL Magnetic Card reader device (such as the Omron V3B-4K).
+ */
+
+#ifndef _MAGSTRIPEHW_H_
+#define _MAGSTRIPEHW_H_
+
+	/* Includes: */
+		#include <avr/io.h>
+
+		#include <LUFA/Common/Common.h>
+		#include "Config/AppConfig.h"
+
+	/* Private Interface - For use in library only: */
+		/* Macros: */
+			/** Mask of the track data, clock and card detection pins. */
+			#define MAG_MASK    (MAG_T1_DATA | MAG_T1_CLOCK | \
+			                     MAG_T2_DATA | MAG_T2_CLOCK | \
+			                     MAG_T3_DATA | MAG_T3_CLOCK | \
+			                     MAG_CARDPRESENT)
+
+	/* Public Interface - May be used in end-application: */
+		/* Inline Functions: */
+			/** Initializes the magnetic stripe card reader ports and pins so that the card reader
+			 *  device can be controlled and read by the card reader driver. This must be called before
+			 *  trying to read any of the card reader's status lines.
+			 */
+			static inline void Magstripe_Init(void)
+			{
+				MAG_DDR  &= ~MAG_MASK;
+				MAG_PORT |=  MAG_MASK;
+			};
+
+			/** Returns the status of all the magnetic card reader's outputs.
+			 *
+			 *  \return A mask indicating which card lines are high or low
+			 */
+			static inline uint8_t Magstripe_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+			static inline uint8_t Magstripe_GetStatus(void)
+			{
+				/* Mag-stripe IOs are active low and must be inverted when read */
+				return ((uint8_t)~MAG_PIN & MAG_MASK);
+			}
+
+#endif
+
diff --git a/Projects/Magstripe/Magstripe.c b/Projects/Magstripe/Magstripe.c
new file mode 100644
index 0000000000..9bb6ff01a0
--- /dev/null
+++ b/Projects/Magstripe/Magstripe.c
@@ -0,0 +1,228 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2017.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2010  Denver Gingerich (denver [at] ossguy [dot] com)
+  Copyright 2017  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 MagStripe reader program. This file contains the main tasks of
+ *  the project and is responsible for the initial application hardware configuration.
+ */
+
+#include "Magstripe.h"
+
+/** Bit buffers to hold the read bits for each of the three magnetic card tracks before they are transmitted
+ *  to the host as keyboard presses.
+ */
+static BitBuffer_t TrackDataBuffers[TOTAL_TRACKS];
+
+/** Pointer to the current track buffer being sent to the host. */
+static BitBuffer_t* CurrentTrackBuffer = &TrackDataBuffers[TOTAL_TRACKS];
+
+/** Buffer to hold the previously generated Keyboard HID report, for comparison purposes inside the HID class driver. */
+static uint8_t PrevKeyboardHIDReportBuffer[sizeof(USB_KeyboardReport_Data_t)];
+
+/** 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 Keyboard_HID_Interface =
+	{
+		.Config =
+			{
+				.InterfaceNumber            = INTERFACE_ID_Keyboard,
+				.ReportINEndpoint           =
+					{
+						.Address            = KEYBOARD_EPADDR,
+						.Size               = KEYBOARD_EPSIZE,
+						.Banks              = 1,
+					},
+				.PrevReportINBuffer         = PrevKeyboardHIDReportBuffer,
+				.PrevReportINBufferSize     = sizeof(PrevKeyboardHIDReportBuffer),
+			},
+	};
+
+
+/** 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();
+
+	for (uint8_t Buffer = 0; Buffer < TOTAL_TRACKS; Buffer++)
+	  BitBuffer_Init(&TrackDataBuffers[Buffer]);
+
+	GlobalInterruptEnable();
+
+	for (;;)
+	{
+		if (Magstripe_GetStatus() & MAG_CARDPRESENT)
+		  ReadMagstripeData();
+
+		HID_Device_USBTask(&Keyboard_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);
+#endif
+
+	/* Hardware Initialization */
+	Magstripe_Init();
+	USB_Init();
+}
+
+/** Determines if a card has been inserted, and if so reads in each track's contents into the bit buffers
+ *  until they are read out to the host as a series of keyboard presses.
+ */
+void ReadMagstripeData(void)
+{
+	/* Arrays to hold the buffer pointers, clock and data bit masks for the separate card tracks */
+	const struct
+	{
+		uint8_t ClockMask;
+		uint8_t DataMask;
+	} TrackInfo[] = {{MAG_T1_CLOCK, MAG_T1_DATA},
+	                 {MAG_T2_CLOCK, MAG_T2_DATA},
+	                 {MAG_T3_CLOCK, MAG_T3_DATA}};
+
+	uint8_t Magstripe_Prev = 0;
+	uint8_t Magstripe_LCL  = Magstripe_GetStatus();
+
+	while (Magstripe_LCL & MAG_CARDPRESENT)
+	{
+		for (uint8_t Track = 0; Track < TOTAL_TRACKS; Track++)
+		{
+			bool DataPinLevel      = ((Magstripe_LCL & TrackInfo[Track].DataMask) != 0);
+			bool ClockPinLevel     = ((Magstripe_LCL & TrackInfo[Track].ClockMask) != 0);
+			bool ClockLevelChanged = (((Magstripe_LCL ^ Magstripe_Prev) & TrackInfo[Track].ClockMask) != 0);
+
+			/* Sample data on rising clock edges from the card reader */
+			if (ClockPinLevel && ClockLevelChanged)
+			  BitBuffer_StoreNextBit(&TrackDataBuffers[Track], DataPinLevel);
+		}
+
+		Magstripe_Prev = Magstripe_LCL;
+		Magstripe_LCL  = Magstripe_GetStatus();
+	}
+
+	CurrentTrackBuffer = &TrackDataBuffers[0];
+}
+
+/** Event handler for the library USB Configuration Changed event. */
+void EVENT_USB_Device_ConfigurationChanged(void)
+{
+	HID_Device_ConfigureEndpoints(&Keyboard_HID_Interface);
+
+	USB_Device_EnableSOFEvents();
+}
+
+/** Event handler for the library USB Control Request reception event. */
+void EVENT_USB_Device_ControlRequest(void)
+{
+	HID_Device_ProcessControlRequest(&Keyboard_HID_Interface);
+}
+
+/** Event handler for the USB device Start Of Frame event. */
+void EVENT_USB_Device_StartOfFrame(void)
+{
+	HID_Device_MillisecondElapsed(&Keyboard_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)
+{
+	USB_KeyboardReport_Data_t* KeyboardReport = (USB_KeyboardReport_Data_t*)ReportData;
+
+	static bool IsKeyReleaseReport;
+
+	/* Key reports must be interleaved with key release reports, or repeated keys will be ignored */
+	IsKeyReleaseReport = !IsKeyReleaseReport;
+
+	if ((IsKeyReleaseReport) || (CurrentTrackBuffer == &TrackDataBuffers[TOTAL_TRACKS]))
+	{
+		/* No more data to send, or key release report between key presses */
+		KeyboardReport->KeyCode[0] = KEY_NONE;
+	}
+	else if (!(CurrentTrackBuffer->Elements))
+	{
+		/* End of current track, send an enter press and change to the next track's buffer */
+		KeyboardReport->KeyCode[0] = KEY_ENTER;
+		CurrentTrackBuffer++;
+	}
+	else
+	{
+		/* Still data in the current track; convert next bit to a 1 or 0 keypress */
+		KeyboardReport->KeyCode[0] = BitBuffer_GetNextBit(CurrentTrackBuffer) ? KEY_1 : KEY_0;
+	}
+
+	*ReportSize = sizeof(USB_KeyboardReport_Data_t);
+	return false;
+}
+
+/** HID Class driver callback function for the processing of a received HID report from the host.
+ *
+ *  \param[in] HIDInterfaceInfo  Pointer to the HID interface structure for the HID interface 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 the report buffer where the received report is stored
+ *  \param[in] ReportSize        Size in bytes of the report received from the host
+ */
+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)
+{
+	// Ignore keyboard LED reports from the host, but still need to declare the callback routine
+}
+
diff --git a/Projects/Magstripe/Magstripe.h b/Projects/Magstripe/Magstripe.h
new file mode 100644
index 0000000000..342cd8ffe5
--- /dev/null
+++ b/Projects/Magstripe/Magstripe.h
@@ -0,0 +1,90 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2017.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2010  Denver Gingerich (denver [at] ossguy [dot] com)
+  Copyright 2017  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 Magstripe.c.
+ */
+
+#ifndef _MAGSTRIPE_H_
+#define _MAGSTRIPE_H_
+
+	/* Includes: */
+		#include <avr/io.h>
+		#include <avr/wdt.h>
+		#include <avr/power.h>
+		#include <avr/interrupt.h>
+
+		#include "Descriptors.h"
+		#include "Lib/MagstripeHW.h"
+		#include "Lib/CircularBitBuffer.h"
+		#include "Config/AppConfig.h"
+
+		#include <LUFA/Drivers/USB/USB.h>
+		#include <LUFA/Platform/Platform.h>
+
+	/* Macros: */
+		/** Total number of tracks which can be read from the card, between 1 and 3. */
+		#define TOTAL_TRACKS       3
+
+		/** HID keyboard keycode to indicate that no is currently pressed. */
+		#define KEY_NONE           0
+
+		/** HID keyboard keycode to indicate that the "1" key is currently pressed. */
+		#define KEY_1              30
+
+		/** HID keyboard keycode to indicate that the "0" key is currently pressed. */
+		#define KEY_0              39
+
+		/** HID keyboard keycode to indicate that the enter key is currently pressed. */
+		#define KEY_ENTER          40
+
+	/* Function Prototypes: */
+		void SetupHardware(void);
+		void ReadMagstripeData(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
+
diff --git a/Projects/Magstripe/Magstripe.txt b/Projects/Magstripe/Magstripe.txt
new file mode 100644
index 0000000000..a11dfaf804
--- /dev/null
+++ b/Projects/Magstripe/Magstripe.txt
@@ -0,0 +1,163 @@
+/** \file
+ *
+ *  This file contains special DoxyGen information for the generation of the main page and other special
+ *  documentation pages. It is not a project source file.
+ */
+
+/** \mainpage Denver Gingerich's USBSnoop Magnetic Card Reader Project
+ *
+ *  \section Sec_Compat Project Compatibility:
+ *
+ *  The following list indicates what microcontrollers are compatible with this project.
+ *
+ *  \li AT90USB1287
+ *  \li AT90USB1286
+ *
+ *  \section Sec_Info USB Information:
+ *
+ *  The following table gives a rundown of the USB utilization of this project.
+ *
+ * <table>
+ *  <tr>
+ *   <td><b>USB Mode:</b></td>
+ *   <td>Device</td>
+ *  </tr>
+ *  <tr>
+ *   <td><b>USB Class:</b></td>
+ *   <td>Human Interface Device (HID)</td>
+ *  </tr>
+ *  <tr>
+ *   <td><b>USB Subclass:</b></td>
+ *   <td>Keyboard</td>
+ *  </tr>
+ *  <tr>
+ *   <td><b>Relevant Standards:</b></td>
+ *   <td>USBIF HID Standard, USBIF HID Usage Tables</td>
+ *  </tr>
+ *  <tr>
+ *   <td><b>Supported USB Speeds:</b></td>
+ *   <td>Full Speed Mode</td>
+ *  </tr>
+ * </table>
+ *
+ *  \section Sec_Description Project Description:
+ *
+ *  Firmware for a USB AVR powered USB TTL magnetic stripe reader (using a card
+ *  reader such as the Omron V3B-4K) by Denver Gingerich. This project is designed
+ *  to be used with the open source Stripe Snoop project at <a>http://stripesnoop.sourceforge.net/</a>.
+ *
+ *  See <a>http://ossguy.com/ss_usb/</a> for the USB reader hardware project website,
+ *  including construction and support details.
+ *
+ *  To use, connect your magnetic card reader device to the USB AVR as follows (pin and port mapping may be adjusted
+ *  from the project makefile):
+ *
+ *  <table>
+ *   <tr>
+ *    <th><b>Signal:</b></th>
+ *    <th><b>AVR Port:</b></th>
+ *   </tr>
+ *   <tr>
+ *    <td>Track 1 Data</td>
+ *    <td>PORTC, Pin 1</td>
+ *   </tr>
+ *   <tr>
+ *    <td>Track 1 Clock</td>
+ *    <td>PORTC, Pin 2</td>
+ *   </tr>
+ *   <tr>
+ *    <td>Track 2 Data</td>
+ *    <td>PORTC, Pin 3</td>
+ *   </tr>
+ *   <tr>
+ *    <td>Track 2 Clock</td>
+ *    <td>PORTC, Pin 0</td>
+ *   </tr>
+ *   <tr>
+ *    <td>Track 3 Data</td>
+ *    <td>PORTC, Pin 5</td>
+ *   </tr>
+ *   <tr>
+ *    <td>Track 3 Clock</td>
+ *    <td>PORTC, Pin 6</td>
+ *   </tr>
+ *   <tr>
+ *    <td>Card Detect</td>
+ *    <td>PORTC, Pin 4</td>
+ *   </tr>
+ *  </table>
+ *
+ *  This project is based on the LUFA Keyboard project demonstration application, written by Denver Gingerich.
+ *
+ *  This application uses a keyboard HID driver to communicate the data collected a TTL magnetic stripe reader
+ *  to the connected computer. The raw bitstream obtained from the magnetic stripe reader is "typed" through
+ *  the keyboard driver as 0's and 1's. After every card swipe, the project will send a return key.
+ *
+ *  \section Sec_Options Project Options
+ *
+ *  The following defines can be found in this project, which can control the project behaviour when defined, or changed in value.
+ *
+ *  <table>
+ *   <tr>
+ *    <th><b>Define Name:</b></th>
+ *    <th><b>Location:</b></th>
+ *    <th><b>Description:</b></th>
+ *   </tr>
+ *   <tr>
+ *    <td>MAX_BITS</td>
+ *    <td>CircularBitBuffer.h</td>
+ *    <td>Gives the maximum number of bits per track which can be buffered by the device for later transmission to a host.</td>
+ *   </tr>
+ *   <tr>
+ *    <td>MAG_T1_CLOCK</td>
+ *    <td>AppConfig.h</td>
+ *    <td>Mask for the magnetic card reader's CLOCK line for the reader's track 1 output.</td>
+ *   </tr>
+ *   <tr>
+ *    <td>MAG_T1_DATA</td>
+ *    <td>AppConfig.h</td>
+ *    <td>Mask for the magnetic card reader's DATA line for the reader's track 1 output.</td>
+ *   </tr>
+ *   <tr>
+ *    <td>MAG_T2_CLOCK</td>
+ *    <td>AppConfig.h</td>
+ *    <td>Mask for the magnetic card reader's CLOCK line for the reader's track 2 output.</td>
+ *   </tr>
+ *   <tr>
+ *    <td>MAG_T2_DATA</td>
+ *    <td>AppConfig.h</td>
+ *    <td>Mask for the magnetic card reader's DATA line for the reader's track 2 output.</td>
+ *   </tr>
+ *   <tr>
+ *    <td>MAG_T3_CLOCK</td>
+ *    <td>AppConfig.h</td>
+ *    <td>Mask for the magnetic card reader's CLOCK line for the reader's track 3 output.</td>
+ *   </tr>
+ *   <tr>
+ *    <td>MAG_T3_DATA</td>
+ *    <td>AppConfig.h</td>
+ *    <td>Mask for the magnetic card reader's DATA line for the reader's track 3 output.</td>
+ *   </tr>
+ *   <tr>
+ *    <td>MAG_CARDPRESENT</td>
+ *    <td>AppConfig.h</td>
+ *    <td>Mask for the magnetic card reader's card detection output.</td>
+ *   </tr>
+ *   <tr>
+ *    <td>MAG_PIN</td>
+ *    <td>AppConfig.h</td>
+ *    <td>PIN register that the magnetic card reader device is attached to.</td>
+ *   </tr>
+ *   <tr>
+ *    <td>MAG_PORT</td>
+ *    <td>AppConfig.h</td>
+ *    <td>PORT register that the magnetic card reader device is attached to.</td>
+ *   </tr>
+ *   <tr>
+ *    <td>MAG_DDR</td>
+ *    <td>AppConfig.h</td>
+ *    <td>DDR register that the magnetic card reader device is attached to.</td>
+ *   </tr>
+ *  </table>
+ */
+
diff --git a/Projects/Magstripe/asf.xml b/Projects/Magstripe/asf.xml
new file mode 100644
index 0000000000..9fc5311e26
--- /dev/null
+++ b/Projects/Magstripe/asf.xml
@@ -0,0 +1,52 @@
+<asf xmlversion="1.0">
+	<project caption="Magnetic Strip Card Reader" id="lufa.projects.magstripe.avr8">
+		<require idref="lufa.projects.magstripe"/>
+		<require idref="lufa.boards.dummy.avr8"/>
+		<generator value="as5_8"/>
+
+		<device-support value="at90usb1287"/>
+		<config name="lufa.drivers.board.name" value="usbkey"/>
+
+		<build type="define" name="F_CPU" value="8000000UL"/>
+		<build type="define" name="F_USB" value="8000000UL"/>
+	</project>
+
+	<module type="application" id="lufa.projects.magstripe" caption="Magnetic Strip Card Reader">
+		<info type="description" value="summary">
+		Magnetic strip card reader project.
+		</info>
+
+ 		<info type="gui-flag" value="move-to-root"/>
+
+		<info type="keyword" value="Technology">
+			<keyword value="Class Driver APIs"/>
+			<keyword value="USB Device"/>
+			<keyword value="HID Class"/>
+		</info>
+
+		<device-support-alias value="lufa_avr8"/>
+		<device-support-alias value="lufa_xmega"/>
+		<device-support-alias value="lufa_uc3"/>
+
+		<build type="distribute" subtype="user-file" value="doxyfile"/>
+		<build type="distribute" subtype="user-file" value="Magstripe.txt"/>
+
+		<build type="c-source" value="Magstripe.c"/>
+		<build type="c-source" value="Descriptors.c"/>
+		<build type="header-file" value="Magstripe.h"/>
+		<build type="header-file" value="Descriptors.h"/>
+
+		<build type="c-source" value="Lib/CircularBitBuffer.c"/>
+		<build type="header-file" value="Lib/CircularBitBuffer.h"/>
+		<build type="header-file" value="Lib/MagstripeHW.h"/>
+
+		<build type="module-config" subtype="path" value="Config"/>
+		<build type="module-config" subtype="required-header-file" value="AppConfig.h"/>
+		<build type="header-file" value="Config/AppConfig.h"/>
+		<build type="header-file" value="Config/LUFAConfig.h"/>
+
+		<require idref="lufa.common"/>
+		<require idref="lufa.platform"/>
+		<require idref="lufa.drivers.usb"/>
+	</module>
+</asf>
diff --git a/Projects/Magstripe/doxyfile b/Projects/Magstripe/doxyfile
new file mode 100644
index 0000000000..23554c194b
--- /dev/null
+++ b/Projects/Magstripe/doxyfile
@@ -0,0 +1,2395 @@
+# Doxyfile 1.8.9
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME           = "Denver Gingerich's Stripe Snoop Project"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER         =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          =
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = ./Documentation/
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES    = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES        = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES            = YES
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES                =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST              =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for