X-Git-Url: http://git.linex4red.de/pub/lufa.git/blobdiff_plain/ea922c98d187eb74c31535afa3334ead5bd50526..063474561de084fbdd8c1ddc02fcce5b8abebe3e:/Projects/AVRISP-MKII/Descriptors.c diff --git a/Projects/AVRISP-MKII/Descriptors.c b/Projects/AVRISP-MKII/Descriptors.c index 9889820cf..0a43dc902 100644 --- a/Projects/AVRISP-MKII/Descriptors.c +++ b/Projects/AVRISP-MKII/Descriptors.c @@ -1,13 +1,13 @@ /* LUFA Library - Copyright (C) Dean Camera, 2011. + Copyright (C) Dean Camera, 2012. dean [at] fourwalledcubicle [dot] com www.lufa-lib.org */ /* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + Copyright 2012 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 @@ -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 @@ -53,8 +63,8 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE, - .VendorID = CPU_TO_LE16(0x03EB), - .ProductID = CPU_TO_LE16(0x2104), + .VendorID = 0x03EB, + .ProductID = 0x2104, .ReleaseNumber = VERSION_BCD(02.00), .ManufacturerStrIndex = 0x01, @@ -69,19 +79,19 @@ 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 = { .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration}, - .TotalConfigurationSize = CPU_TO_LE16(sizeof(USB_Descriptor_Configuration_t)), + .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t), .TotalInterfaces = 1, .ConfigurationNumber = 1, .ConfigurationStrIndex = NO_DESCRIPTOR, - .ConfigAttributes = USB_CONFIG_ATTR_BUSPOWERED, + .ConfigAttributes = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_SELFPOWERED), .MaxPowerConsumption = USB_CONFIG_POWER_MA(100) }, @@ -96,8 +106,8 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = .TotalEndpoints = 2, .Class = USB_CSCP_VendorSpecificClass, - .SubClass = 0x00, - .Protocol = 0x00, + .SubClass = USB_CSCP_NoDeviceSubclass, + .Protocol = USB_CSCP_NoDeviceProtocol, .InterfaceStrIndex = NO_DESCRIPTOR }, @@ -106,9 +116,13 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = { .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, - .EndpointAddress = (ENDPOINT_DESCRIPTOR_DIR_IN | AVRISP_DATA_IN_EPNUM), +#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 = CPU_TO_LE16(AVRISP_DATA_EPSIZE), + .EndpointSize = AVRISP_DATA_EPSIZE, .PollingIntervalMS = 0x0A }, @@ -116,9 +130,9 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = { .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, - .EndpointAddress = (ENDPOINT_DESCRIPTOR_DIR_OUT | AVRISP_DATA_OUT_EPNUM), + .EndpointAddress = AVRISP_DATA_OUT_EPADDR, .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), - .EndpointSize = CPU_TO_LE16(AVRISP_DATA_EPSIZE), + .EndpointSize = AVRISP_DATA_EPSIZE, .PollingIntervalMS = 0x0A }, }; @@ -140,19 +154,9 @@ const USB_Descriptor_String_t PROGMEM LanguageString = */ const USB_Descriptor_String_t PROGMEM ManufacturerString = { - .Header = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String}, + .Header = {.Size = USB_STRING_LEN(5), .Type = DTYPE_String}, - .UnicodeString = {CPU_TO_LE16('D'), - CPU_TO_LE16('e'), - CPU_TO_LE16('a'), - CPU_TO_LE16('n'), - CPU_TO_LE16(' '), - CPU_TO_LE16('C'), - CPU_TO_LE16('a'), - CPU_TO_LE16('m'), - CPU_TO_LE16('e'), - CPU_TO_LE16('r'), - CPU_TO_LE16('a')} + .UnicodeString = L"ATMEL" }; /** Product descriptor string. This is a Unicode string containing the product's details in human readable form, @@ -161,30 +165,9 @@ const USB_Descriptor_String_t PROGMEM ManufacturerString = */ const USB_Descriptor_String_t PROGMEM ProductString = { - .Header = {.Size = USB_STRING_LEN(22), .Type = DTYPE_String}, - - .UnicodeString = {CPU_TO_LE16('L'), - CPU_TO_LE16('U'), - CPU_TO_LE16('F'), - CPU_TO_LE16('A'), - CPU_TO_LE16(' '), - CPU_TO_LE16('A'), - CPU_TO_LE16('V'), - CPU_TO_LE16('R'), - CPU_TO_LE16('I'), - CPU_TO_LE16('S'), - CPU_TO_LE16('P'), - CPU_TO_LE16(' '), - CPU_TO_LE16('M'), - CPU_TO_LE16('k'), - CPU_TO_LE16('I'), - CPU_TO_LE16('I'), - CPU_TO_LE16(' '), - CPU_TO_LE16('C'), - CPU_TO_LE16('l'), - CPU_TO_LE16('o'), - CPU_TO_LE16('n'), - CPU_TO_LE16('e')} + .Header = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String}, + + .UnicodeString = L"AVRISP mkII" }; /** Serial number string. This is a Unicode string containing the device's unique serial number, expressed as a @@ -193,20 +176,8 @@ const USB_Descriptor_String_t PROGMEM ProductString = const USB_Descriptor_String_t PROGMEM SerialString = { .Header = {.Size = USB_STRING_LEN(13), .Type = DTYPE_String}, - - .UnicodeString = {CPU_TO_LE16('0'), - CPU_TO_LE16('0'), - CPU_TO_LE16('0'), - CPU_TO_LE16('0'), - CPU_TO_LE16('A'), - CPU_TO_LE16('0'), - CPU_TO_LE16('0'), - CPU_TO_LE16('1'), - CPU_TO_LE16('2'), - CPU_TO_LE16('8'), - CPU_TO_LE16('2'), - CPU_TO_LE16('5'), - CPU_TO_LE16('5')} + + .UnicodeString = L"000200012345\0" // Note: Real AVRISP-MKII has the embedded NUL byte, bug in firmware? }; /** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors" @@ -217,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); @@ -225,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: @@ -232,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; @@ -263,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