diff --git a/LUFA/DoxygenPages/ChangeLog.txt b/LUFA/DoxygenPages/ChangeLog.txt
index ffc4dfee7e..7758f8b942 100644
--- a/LUFA/DoxygenPages/ChangeLog.txt
+++ b/LUFA/DoxygenPages/ChangeLog.txt
@@ -22,6 +22,7 @@
* - Modified the CDC Host demos to set a default CDC Line Encoding on enumerated devices
* - Added Dataflash operational checks and aborts to all projects using the Dataflash to ensure it is working correctly before use
* - Added new SerialToLCD user project contributed by Simon Foster
+ * - Added new RESET_TOGGLES_LIBUSB_COMPAT compile time option to the AVRISP-MKII clone programmer project (thanks to Robert Spitzenpfeil)
*
* Changed:
* - Core:
diff --git a/Projects/AVRISP-MKII/AVRISP-MKII.c b/Projects/AVRISP-MKII/AVRISP-MKII.c
index eaf04cb7a3..236a2a8782 100644
--- a/Projects/AVRISP-MKII/AVRISP-MKII.c
+++ b/Projects/AVRISP-MKII/AVRISP-MKII.c
@@ -72,6 +72,11 @@ void SetupHardware(void)
/* Hardware Initialization */
LEDs_Init();
+ #if defined(RESET_TOGGLES_LIBUSB_COMPAT)
+ UpdateCurrentCompatibilityMode();
+ #endif
+
+ /* USB Stack Initialization */
USB_Init();
}
diff --git a/Projects/AVRISP-MKII/AVRISP-MKII.txt b/Projects/AVRISP-MKII/AVRISP-MKII.txt
index 6b2badca7b..3d43cb137d 100644
--- a/Projects/AVRISP-MKII/AVRISP-MKII.txt
+++ b/Projects/AVRISP-MKII/AVRISP-MKII.txt
@@ -293,7 +293,18 @@
*
LIBUSB_DRIVER_COMPAT |
* Makefile LUFA_OPTS |
* Define to switch to a non-standard endpoint scheme, breaking compatibility with AVRStudio under Windows but making
- * the code compatible with software such as avrdude (all platforms) that use the libUSB driver. |
+ * the code compatible with software such as avrdude (all platforms) that use the libUSB driver.
+ *
+ * \note This option is incompatible with \c RESET_TOGGLES_LIBUSB_COMPAT.
+ *
+ *
+ * RESET_TOGGLES_LIBUSB_COMPAT |
+ * Makefile LUFA_OPTS |
+ * Define to make the /RESET line of the AVR toggle between Jungo and libUSB driver compatibility modes. Each time the AVR is
+ * reset externally via the reset pin, the compatibility mode will be toggled. The compatibility mode is preserved between
+ * power cycles and is not toggled via other forms of reset such as Watchdog or Brown Out.
+ *
+ * \note This option is incompatible with \c LIBUSB_DRIVER_COMPAT. |
*
*
* XCK_RESCUE_CLOCK_ENABLE |
diff --git a/Projects/AVRISP-MKII/Descriptors.c b/Projects/AVRISP-MKII/Descriptors.c
index da57b7113c..0a43dc9020 100644
--- a/Projects/AVRISP-MKII/Descriptors.c
+++ b/Projects/AVRISP-MKII/Descriptors.c
@@ -37,6 +37,16 @@
#include "Descriptors.h"
+#if defined(RESET_TOGGLES_LIBUSB_COMPAT) || defined(__DOXYGEN__)
+ static bool AVRISP_NeedCompatibilitySwitch ATTR_NO_INIT;
+
+ /** Current AVRISP data IN endpoint address. */
+ uint8_t AVRISP_CurrDataINEndpointAddress;
+
+ /** Saved AVRISP data IN endpoint address in EEPROM. */
+ uint8_t AVRISP_CurrDataINEndpointAddress_EEPROM EEMEM;
+#endif
+
/** 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
@@ -69,7 +79,7 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
* 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 =
+USB_Descriptor_Configuration_t ConfigurationDescriptor =
{
.Config =
{
@@ -106,7 +116,11 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+#if defined(RESET_TOGGLES_LIBUSB_COMPAT)
+ .EndpointAddress = 0,
+#else
.EndpointAddress = AVRISP_DATA_IN_EPADDR,
+#endif
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = AVRISP_DATA_EPSIZE,
.PollingIntervalMS = 0x0A
@@ -174,7 +188,8 @@ const USB_Descriptor_String_t PROGMEM SerialString =
*/
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
const uint8_t wIndex,
- const void** const DescriptorAddress)
+ const void** const DescriptorAddress,
+ uint8_t* DescriptorMemorySpace)
{
const uint8_t DescriptorType = (wValue >> 8);
const uint8_t DescriptorNumber = (wValue & 0xFF);
@@ -182,6 +197,8 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
const void* Address = NULL;
uint16_t Size = NO_DESCRIPTOR;
+ *DescriptorMemorySpace = MEMSPACE_FLASH;
+
switch (DescriptorType)
{
case DTYPE_Device:
@@ -189,6 +206,11 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
Size = sizeof(USB_Descriptor_Device_t);
break;
case DTYPE_Configuration:
+ *DescriptorMemorySpace = MEMSPACE_RAM;
+ #if defined(RESET_TOGGLES_LIBUSB_COMPAT)
+ ConfigurationDescriptor.AVRISP_DataInEndpoint.EndpointAddress = AVRISP_CurrDataINEndpointAddress;
+ #endif
+
Address = &ConfigurationDescriptor;
Size = sizeof(USB_Descriptor_Configuration_t);
break;
@@ -220,3 +242,70 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
return Size;
}
+#if defined(RESET_TOGGLES_LIBUSB_COMPAT) || defined(__DOXYGEN__)
+/** Checks the state of the system status register MCUSR and indicates via a flag if
+ * the current AVRISP driver compatibility mode needs to be reset.
+ *
+ * When the \c RESET_TOGGLES_LIBUSB_COMPAT compile time option is enabled, pulling
+ * the reset line of the AVR low will toggle between Jungo and libUSB compatibility
+ * modes. Other forms of reset (such as power on or watchdog) will not force a mode
+ * change.
+ */
+void CheckExternalReset(void)
+{
+ /* If an external reset occured, we need to change compatibility mode */
+ AVRISP_NeedCompatibilitySwitch = (MCUSR == (1 << EXTRF));
+
+ MCUSR = 0;
+}
+
+/** Updates the device descriptors so that the correct compatibility mode is used
+ * when the \c RESET_TOGGLES_LIBUSB_COMPAT compile time option is enabled. This
+ * configures the programmer for either Jungo or libUSB driver compatibility. Each
+ * time the AVR is reset via pulling the reset line low the compatibility mode will
+ * be toggled. The current mode is stored in EEPROM and preserved through power
+ * cycles of the AVR.
+ */
+void UpdateCurrentCompatibilityMode(void)
+{
+ /* Load the current IN endpoint address stored in EEPROM */
+ AVRISP_CurrDataINEndpointAddress = eeprom_read_byte(&AVRISP_CurrDataINEndpointAddress_EEPROM);
+
+ /* Check if we need to switch compatibility modes */
+ if (AVRISP_NeedCompatibilitySwitch)
+ {
+ /* Toggle between compatibility modes */
+ AVRISP_CurrDataINEndpointAddress = (AVRISP_CurrDataINEndpointAddress == AVRISP_DATA_IN_EPADDR_LIBUSB) ?
+ AVRISP_DATA_IN_EPADDR_JUNGO : AVRISP_DATA_IN_EPADDR_LIBUSB;
+
+ /* Save the new mode into EEPROM */
+ eeprom_update_byte(&AVRISP_CurrDataINEndpointAddress_EEPROM, AVRISP_CurrDataINEndpointAddress);
+ }
+
+ LEDs_SetAllLEDs(LEDS_NO_LEDS);
+
+ /* Validate IN endpoint address and indicate current mode via LED flashes */
+ switch (AVRISP_CurrDataINEndpointAddress)
+ {
+ default:
+ /* Default to Jungo compatibility mode if saved EEPROM is invalid */
+ AVRISP_CurrDataINEndpointAddress = AVRISP_DATA_IN_EPADDR_JUNGO;
+ case AVRISP_DATA_IN_EPADDR_JUNGO:
+ /* Two flashes for Jungo compatibility mode */
+ for (uint8_t i = 0; i < 4; i++)
+ {
+ LEDs_ToggleLEDs(LEDS_ALL_LEDS);
+ Delay_MS(100);
+ }
+ break;
+ case AVRISP_DATA_IN_EPADDR_LIBUSB:
+ /* Five flashes for libUSB compatibility mode */
+ for (uint8_t i = 0; i < 10; i++)
+ {
+ LEDs_ToggleLEDs(LEDS_ALL_LEDS);
+ Delay_MS(100);
+ }
+ break;
+ }
+}
+#endif
diff --git a/Projects/AVRISP-MKII/Descriptors.h b/Projects/AVRISP-MKII/Descriptors.h
index 1b140f30df..675291afb9 100644
--- a/Projects/AVRISP-MKII/Descriptors.h
+++ b/Projects/AVRISP-MKII/Descriptors.h
@@ -40,19 +40,32 @@
#include
#include
+ #include
+
+ /* Preprocessor Checks: */
+ #if defined(LIBUSB_DRIVER_COMPAT) && defined(RESET_TOGGLES_LIBUSB_COMPAT)
+ #error LIBUSB_DRIVER_COMPAT and RESET_TOGGLES_LIBUSB_COMPAT are mutually exclusive.
+ #endif
/* Macros: */
- #if !defined(LIBUSB_DRIVER_COMPAT) || defined(__DOXYGEN__)
- /** Endpoint address of the AVRISP data OUT endpoint. */
- #define AVRISP_DATA_OUT_EPADDR (ENDPOINT_DIR_OUT | 2)
+ /** Endpoint address of the AVRISP data OUT endpoint. */
+ #define AVRISP_DATA_OUT_EPADDR (ENDPOINT_DIR_OUT | 2)
+
+ /** Endpoint address of the AVRISP data IN endpoint, when in Jungo driver compatibility mode. */
+ #define AVRISP_DATA_IN_EPADDR_JUNGO (ENDPOINT_DIR_IN | 2)
+
+ /** Endpoint address of the AVRISP data IN endpoint, when in LibUSB driver compatibility mode. */
+ #define AVRISP_DATA_IN_EPADDR_LIBUSB (ENDPOINT_DIR_IN | 3)
+ #if !defined(LIBUSB_DRIVER_COMPAT) || defined(__DOXYGEN__)
/** Endpoint address of the AVRISP data IN endpoint. */
- #define AVRISP_DATA_IN_EPADDR (ENDPOINT_DIR_IN | 2)
+ #define AVRISP_DATA_IN_EPADDR AVRISP_DATA_IN_EPADDR_JUNGO
+ #elif defined(RESET_TOGGLES_LIBUSB_COMPAT)
+ #define AVRISP_DATA_IN_EPADDR AVRISP_CurrDataINEndpointAddress
#else
- #define AVRISP_DATA_OUT_EPADDR (ENDPOINT_DIR_OUT | 2)
- #define AVRISP_DATA_IN_EPADDR (ENDPOINT_DIR_IN | 3)
+ #define AVRISP_DATA_IN_EPADDR AVRISP_DATA_IN_EPADDR_LIBUSB
#endif
-
+
/** Size in bytes of the AVRISP data endpoint. */
#define AVRISP_DATA_EPSIZE 64
@@ -71,11 +84,22 @@
USB_Descriptor_Endpoint_t AVRISP_DataOutEndpoint;
} USB_Descriptor_Configuration_t;
+ /* External Variables: */
+ #if defined(RESET_TOGGLES_LIBUSB_COMPAT)
+ extern uint8_t AVRISP_CurrDataINEndpointAddress;
+ #endif
+
/* Function Prototypes: */
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
const uint8_t wIndex,
- const void** const DescriptorAddress)
- ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
+ const void** const DescriptorAddress,
+ uint8_t* const DescriptorMemorySpace)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3) ATTR_NON_NULL_PTR_ARG(4);
+
+ #if defined(RESET_TOGGLES_LIBUSB_COMPAT)
+ void CheckExternalReset(void) ATTR_NAKED ATTR_INIT_SECTION(3);
+ void UpdateCurrentCompatibilityMode(void);
+ #endif
#endif
diff --git a/Projects/AVRISP-MKII/makefile b/Projects/AVRISP-MKII/makefile
index 795456ab71..cf1e99515b 100644
--- a/Projects/AVRISP-MKII/makefile
+++ b/Projects/AVRISP-MKII/makefile
@@ -125,7 +125,6 @@ LUFA_OPTS += -D DEVICE_STATE_AS_GPIOR=0
LUFA_OPTS += -D ORDERED_EP_CONFIG
LUFA_OPTS += -D FIXED_CONTROL_ENDPOINT_SIZE=16
LUFA_OPTS += -D FIXED_NUM_CONFIGURATIONS=1
-LUFA_OPTS += -D USE_FLASH_DESCRIPTORS
LUFA_OPTS += -D USE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
LUFA_OPTS += -D NO_INTERNAL_SERIAL
LUFA_OPTS += -D NO_DEVICE_REMOTE_WAKEUP
@@ -143,6 +142,7 @@ LUFA_OPTS += -D VTARGET_SCALE_FACTOR=1
#LUFA_OPTS += -D VTARGET_USE_INTERNAL_REF
#LUFA_OPTS += -D NO_VTARGET_DETECT
#LUFA_OPTS += -D LIBUSB_DRIVER_COMPAT
+#LUFA_OPTS += -D RESET_TOGGLES_LIBUSB_COMPAT
#LUFA_OPTS += -D XCK_RESCUE_CLOCK_ENABLE
#LUFA_OPTS += -D INVERTED_ISP_MISO
#LUFA_OPTS += -D FIRMWARE_VERSION_MINOR=0x11