Implementation of several key core USB driver functions for the new USB XMEGA devices.
authorDean Camera <dean@fourwalledcubicle.com>
Thu, 14 Jul 2011 07:19:30 +0000 (07:19 +0000)
committerDean Camera <dean@fourwalledcubicle.com>
Thu, 14 Jul 2011 07:19:30 +0000 (07:19 +0000)
LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h
LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h
LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c
LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h

index 805e8f9..f0a472e 100644 (file)
                         *  \note Restrictions apply on the number, size and type of endpoints which can be used\r
                         *        when running in low speed mode - refer to the USB 2.0 specification.\r
                         */\r
-                       #define USB_DEVICE_OPT_LOWSPEED            (1 << 0)\r
+                       #define USB_DEVICE_OPT_LOWSPEED        (1 << 0)\r
 \r
                        /** Mask for the Options parameter of the \ref USB_Init() function. This indicates that the\r
                         *  USB interface should be initialized in full speed (12Mb/s) mode.\r
                         */\r
-                       #define USB_DEVICE_OPT_FULLSPEED               (0 << 0)\r
+                       #define USB_DEVICE_OPT_FULLSPEED       (0 << 0)\r
                        //@}\r
                        \r
                        /** String descriptor index for the device's unique serial number string descriptor within the device.\r
                         *  On unsupported devices, this will evaluate to \ref NO_DESCRIPTOR and so will force the host to create a pseudo-serial\r
                         *  number for the device.\r
                         */\r
-                       #define USE_INTERNAL_SERIAL            NO_DESCRIPTOR\r
+                       #define USE_INTERNAL_SERIAL            0xDC\r
 \r
                        /** Length of the device's unique internal serial number, in bits, if present on the selected microcontroller\r
                         *  model.\r
                         */\r
-                       #define INTERNAL_SERIAL_LENGTH_BITS    0\r
+                       #define INTERNAL_SERIAL_LENGTH_BITS    112\r
                        \r
                        /** Start address of the internal serial number, in the appropriate address space, if present on the selected microcontroller\r
                         *  model.\r
                         */\r
-                       #define INTERNAL_SERIAL_START_ADDRESS  0                        \r
+                       #define INTERNAL_SERIAL_START_ADDRESS  0x08\r
                        \r
                /* Function Prototypes: */\r
                        /** Sends a Remote Wakeup request to the host. This signals to the host that the device should\r
                        static inline void USB_Device_SetLowSpeed(void) ATTR_ALWAYS_INLINE;\r
                        static inline void USB_Device_SetLowSpeed(void)\r
                        {\r
-                               // TODO\r
+                               USB.CTRLA &= ~USB_SPEED_bm;\r
                        }\r
 \r
                        static inline void USB_Device_SetFullSpeed(void) ATTR_ALWAYS_INLINE;\r
                        static inline void USB_Device_SetFullSpeed(void)\r
                        {\r
-                               // TODO\r
+                               USB.CTRLA |=  USB_SPEED_bm;\r
                        }\r
 \r
                        static inline void USB_Device_SetDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE;\r
                        static inline void USB_Device_SetDeviceAddress(const uint8_t Address)\r
                        {\r
-                               // TODO\r
+                               USB.ADDR = Address;\r
                        }\r
 \r
                        static inline bool USB_Device_IsAddressSet(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;\r
                        static inline bool USB_Device_IsAddressSet(void)\r
                        {\r
-                               return false; // TODO\r
+                               return ((USB.ADDR != 0) ? true : false);\r
                        }\r
                \r
-                       #if (USE_INTERNAL_SERIAL != NO_DESCRIPTOR)\r
                        static inline void USB_Device_GetSerialString(uint16_t* const UnicodeString) ATTR_NON_NULL_PTR_ARG(1);\r
                        static inline void USB_Device_GetSerialString(uint16_t* const UnicodeString)\r
                        {\r
-                               // TODO\r
+                               uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();\r
+                               GlobalInterruptDisable();\r
+                               \r
+                               uint8_t SigReadAddress = INTERNAL_SERIAL_START_ADDRESS;\r
+\r
+                               for (uint8_t SerialCharNum = 0; SerialCharNum < (INTERNAL_SERIAL_LENGTH_BITS / 4); SerialCharNum++)\r
+                               {                                       \r
+                                       uint8_t SerialByte;\r
+\r
+                                       NVM.CMD    = NVM_CMD_READ_CALIB_ROW_gc;\r
+                                       SerialByte = pgm_read_byte(SigReadAddress);\r
+\r
+                                       if (SerialCharNum & 0x01)\r
+                                       {\r
+                                               SerialByte >>= 4;\r
+                                               SigReadAddress++;\r
+                                       }\r
+\r
+                                       SerialByte &= 0x0F;\r
+\r
+                                       UnicodeString[SerialCharNum] = cpu_to_le16((SerialByte >= 10) ?\r
+                                                                                                                          (('A' - 10) + SerialByte) : ('0' + SerialByte));\r
+                               }\r
+                               \r
+                               SetGlobalInterruptMask(CurrentGlobalInt);\r
+\r
+\r
                        }\r
-                       #endif\r
 \r
        #endif\r
 \r
index e43422e..c444433 100644 (file)
        /* Private Interface - For use in library only: */\r
        #if !defined(__DOXYGEN__)\r
                /* Macros: */\r
-                       #define _ENDPOINT_GET_MAXSIZE(EPIndex)         _ENDPOINT_GET_MAXSIZE2(ENDPOINT_DETAILS_EP ## EPIndex)\r
-                       #define _ENDPOINT_GET_MAXSIZE2(EPDetails)      _ENDPOINT_GET_MAXSIZE3(EPDetails)\r
-                       #define _ENDPOINT_GET_MAXSIZE3(MaxSize, Banks) (MaxSize)\r
-\r
-                       #define _ENDPOINT_GET_BANKS(EPIndex)           _ENDPOINT_GET_BANKS2(ENDPOINT_DETAILS_EP ## EPIndex)\r
-                       #define _ENDPOINT_GET_BANKS2(EPDetails)        _ENDPOINT_GET_BANKS3(EPDetails)\r
-                       #define _ENDPOINT_GET_BANKS3(MaxSize, Banks)   (Banks)\r
-\r
-                       #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)\r
-                               #define ENDPOINT_DETAILS_MAXEP             7\r
-\r
-                               #define ENDPOINT_DETAILS_EP0               64,  1\r
-                               #define ENDPOINT_DETAILS_EP1               256, 2\r
-                               #define ENDPOINT_DETAILS_EP2               64,  2\r
-                               #define ENDPOINT_DETAILS_EP3               64,  2\r
-                               #define ENDPOINT_DETAILS_EP4               64,  2\r
-                               #define ENDPOINT_DETAILS_EP5               64,  2\r
-                               #define ENDPOINT_DETAILS_EP6               64,  2\r
-                       #else\r
-                               #define ENDPOINT_DETAILS_MAXEP             5\r
+                       #define _ENDPOINT_GET_MAXSIZE(EPIndex)         1023\r
+                       #define _ENDPOINT_GET_BANKS(EPIndex)           2\r
 \r
-                               #define ENDPOINT_DETAILS_EP0               64,  1\r
-                               #define ENDPOINT_DETAILS_EP1               64,  1\r
-                               #define ENDPOINT_DETAILS_EP2               64,  1\r
-                               #define ENDPOINT_DETAILS_EP3               64,  2\r
-                               #define ENDPOINT_DETAILS_EP4               64,  2\r
-                       #endif\r
+                       #define ENDPOINT_DETAILS_MAXEP                 16\r
 \r
                /* Inline Functions: */\r
                        static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes) ATTR_WARN_UNUSED_RESULT ATTR_CONST\r
                        /** Endpoint data direction mask for \ref Endpoint_ConfigureEndpoint(). This indicates that the endpoint\r
                         *  should be initialized in the OUT direction - i.e. data flows from host to device.\r
                         */\r
-                       #define ENDPOINT_DIR_OUT                        (0 << EPDIR)\r
+                       #define ENDPOINT_DIR_OUT                        0 // TODO\r
 \r
                        /** Endpoint data direction mask for \ref Endpoint_ConfigureEndpoint(). This indicates that the endpoint\r
                         *  should be initialized in the IN direction - i.e. data flows from device to host.\r
                         */\r
-                       #define ENDPOINT_DIR_IN                         (1 << EPDIR)\r
+                       #define ENDPOINT_DIR_IN                         0 // TODO\r
                        //@}\r
                        \r
                        /** \name Endpoint Bank Mode Masks */\r
                         *  in slower transfers as only one USB device (the AVR or the host) can access the endpoint's\r
                         *  bank at the one time.\r
                         */\r
-                       #define ENDPOINT_BANK_SINGLE                    (0 << EPBK0)\r
+                       #define ENDPOINT_BANK_SINGLE                    0 // TODO\r
 \r
                        /** Mask for the bank mode selection for the \ref Endpoint_ConfigureEndpoint() macro. This indicates\r
                         *  that the endpoint should have two banks, which requires more USB FIFO memory but results\r
                         *  in faster transfers as one USB device (the AVR or the host) can access one bank while the other\r
                         *  accesses the second bank.\r
                         */\r
-                       #define ENDPOINT_BANK_DOUBLE                    (1 << EPBK0)\r
+                       #define ENDPOINT_BANK_DOUBLE                    0 // TODO\r
                        //@}\r
 \r
                        #if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__))\r
index 52d44fe..2556ee8 100644 (file)
@@ -56,22 +56,88 @@ void USB_Init(
                #endif\r
                )\r
 {\r
-       // TODO\r
+       #if !defined(USE_STATIC_OPTIONS)\r
+       USB_Options = Options;\r
+       #endif\r
+       \r
+       USB_IsInitialized = true;\r
+\r
+       USB_ResetInterface();   \r
 }\r
 \r
 void USB_Disable(void)\r
 {\r
-       // TODO\r
+       USB_INT_DisableAllInterrupts();\r
+       USB_INT_ClearAllInterrupts();\r
+\r
+       USB_Detach();\r
+       USB_Controller_Disable();\r
+\r
+       USB_IsInitialized = false;      \r
 }\r
 \r
 void USB_ResetInterface(void)\r
 {\r
-       // TODO\r
+       USB_INT_DisableAllInterrupts();\r
+       USB_INT_ClearAllInterrupts();\r
+\r
+       USB_Controller_Reset();\r
+       USB_Init_Device();\r
 }\r
 \r
 #if defined(USB_CAN_BE_DEVICE)\r
 static void USB_Init_Device(void)\r
 {\r
-       // TODO\r
+       USB_DeviceState                 = DEVICE_STATE_Unattached;\r
+       USB_Device_ConfigurationNumber  = 0;\r
+\r
+       #if !defined(NO_DEVICE_REMOTE_WAKEUP)\r
+       USB_Device_RemoteWakeupEnabled  = false;\r
+       #endif\r
+\r
+       #if !defined(NO_DEVICE_SELF_POWER)\r
+       USB_Device_CurrentlySelfPowered = false;\r
+       #endif\r
+\r
+       #if !defined(FIXED_CONTROL_ENDPOINT_SIZE)\r
+       USB_Descriptor_Device_t* DeviceDescriptorPtr;\r
+       \r
+       #if defined(ARCH_HAS_MULTI_ADDRESS_SPACE) && \\r
+           !(defined(USE_FLASH_DESCRIPTORS) || defined(USE_EEPROM_DESCRIPTORS) || defined(USE_RAM_DESCRIPTORS))\r
+       uint8_t DescriptorAddressSpace;\r
+\r
+       if (CALLBACK_USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DeviceDescriptorPtr, &DescriptorAddressSpace) != NO_DESCRIPTOR)\r
+       {\r
+               if (DescriptorAddressSpace == MEMSPACE_FLASH)\r
+                 USB_Device_ControlEndpointSize = pgm_read_byte(&DeviceDescriptorPtr->Endpoint0Size);\r
+               else if (DescriptorAddressSpace == MEMSPACE_EEPROM)\r
+                 USB_Device_ControlEndpointSize = eeprom_read_byte(&DeviceDescriptorPtr->Endpoint0Size);\r
+               else\r
+                 USB_Device_ControlEndpointSize = DeviceDescriptorPtr->Endpoint0Size;\r
+       }\r
+       #else\r
+       if (CALLBACK_USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DeviceDescriptorPtr) != NO_DESCRIPTOR)\r
+       {\r
+               #if defined(USE_RAM_DESCRIPTORS)\r
+               USB_Device_ControlEndpointSize = DeviceDescriptorPtr->Endpoint0Size;\r
+               #elif defined(USE_EEPROM_DESCRIPTORS)\r
+               USB_Device_ControlEndpointSize = eeprom_read_byte(&DeviceDescriptorPtr->Endpoint0Size);\r
+               #else\r
+               USB_Device_ControlEndpointSize = pgm_read_byte(&DeviceDescriptorPtr->Endpoint0Size);\r
+               #endif\r
+       }       \r
+       #endif\r
+       #endif\r
+\r
+       if (USB_Options & USB_DEVICE_OPT_LOWSPEED)\r
+         USB_Device_SetLowSpeed();\r
+       else\r
+         USB_Device_SetFullSpeed();\r
+\r
+       Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,\r
+                                                          ENDPOINT_DIR_OUT, USB_Device_ControlEndpointSize,\r
+                                                          ENDPOINT_BANK_SINGLE);\r
+\r
+       USB_Attach();\r
 }\r
 #endif\r
index 8be4ed2..f5adc12 100644 (file)
                #endif\r
 \r
        /* Public Interface - May be used in end-application: */\r
-               /* Macros: */\r
-                       /** \name USB Controller Option Masks */\r
-                       //@{\r
-                       /** Regulator disable option mask for \ref USB_Init(). This indicates that the internal 3.3V USB data pad\r
-                        *  regulator should be disabled and the AVR's VCC level used for the data pads.\r
-                        *\r
-                        *  \note See USB AVR data sheet for more information on the internal pad regulator.\r
-                        */\r
-                       #define USB_OPT_REG_DISABLED               (1 << 1)\r
-\r
-                       /** Regulator enable option mask for \ref USB_Init(). This indicates that the internal 3.3V USB data pad\r
-                        *  regulator should be enabled to regulate the data pin voltages from the VBUS level down to a level within\r
-                        *  the range allowable by the USB standard.\r
-                        *\r
-                        *  \note See USB AVR data sheet for more information on the internal pad regulator.\r
-                        */\r
-                       #define USB_OPT_REG_ENABLED                (0 << 1)\r
-\r
-                       /** Manual PLL control option mask for \ref USB_Init(). This indicates to the library that the user application\r
-                        *  will take full responsibility for controlling the AVR's PLL (used to generate the high frequency clock\r
-                        *  that the USB controller requires) and ensuring that it is locked at the correct frequency for USB operations.\r
-                        */\r
-                       #define USB_OPT_MANUAL_PLL                 (1 << 2)\r
-\r
-                       /** Automatic PLL control option mask for \ref USB_Init(). This indicates to the library that the library should\r
-                        *  take full responsibility for controlling the AVR's PLL (used to generate the high frequency clock\r
-                        *  that the USB controller requires) and ensuring that it is locked at the correct frequency for USB operations.\r
-                        */\r
-                       #define USB_OPT_AUTO_PLL                   (0 << 2)\r
-                       //@}\r
-                       \r
+               /* Macros: */                   \r
                        /** \name Endpoint/Pipe Type Masks */\r
                        //@{\r
                        /** Mask for a CONTROL type endpoint or pipe.\r
                         *\r
                         *  \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions.\r
                         */\r
-                       #define EP_TYPE_CONTROL                    0x00\r
+                       #define EP_TYPE_CONTROL                 0x00\r
 \r
                        /** Mask for an ISOCHRONOUS type endpoint or pipe.\r
                         *\r
                         *  \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions.\r
                         */\r
-                       #define EP_TYPE_ISOCHRONOUS                0x01\r
+                       #define EP_TYPE_ISOCHRONOUS             0x01\r
 \r
                        /** Mask for a BULK type endpoint or pipe.\r
                         *\r
                         *  \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions.\r
                         */\r
-                       #define EP_TYPE_BULK                       0x02\r
+                       #define EP_TYPE_BULK                    0x02\r
 \r
                        /** Mask for an INTERRUPT type endpoint or pipe.\r
                         *\r
                         *  \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions.\r
                         */\r
-                       #define EP_TYPE_INTERRUPT                  0x03\r
+                       #define EP_TYPE_INTERRUPT               0x03\r
                        //@}\r
 \r
                        #if !defined(USB_STREAM_TIMEOUT_MS) || defined(__DOXYGEN__)\r
                        #endif\r
 \r
                /* Inline Functions: */\r
-                       /** Determines if the VBUS line is currently high (i.e. the USB host is supplying power).\r
-                        *\r
-                        *  \note This function is not available on some AVR models which do not support hardware VBUS monitoring.\r
-                        *\r
-                        *  \return Boolean \c true if the VBUS line is currently detecting power from a host, \c false otherwise.\r
-                        */\r
-                       static inline bool USB_VBUS_GetStatus(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;\r
-                       static inline bool USB_VBUS_GetStatus(void)\r
-                       {\r
-                               return 0; // TODO\r
-                       }\r
-\r
                        /** Detaches the device from the USB bus. This has the effect of removing the device from any\r
                         *  attached host, ceasing USB communications. If no host is present, this prevents any host from\r
                         *  enumerating the device once attached until \ref USB_Attach() is called.\r
                        static inline void USB_Detach(void) ATTR_ALWAYS_INLINE;\r
                        static inline void USB_Detach(void)\r
                        {\r
-                               // TODO\r
+                               USB.CTRLB &= ~USB_ATTACH_bm;\r
                        }\r
 \r
                        /** Attaches the device to the USB bus. This announces the device's presence to any attached\r
                        static inline void USB_Attach(void) ATTR_ALWAYS_INLINE;\r
                        static inline void USB_Attach(void)\r
                        {\r
-                               // TODO\r
+                               USB.CTRLB |= USB_ATTACH_bm;\r
                        }\r
 \r
                /* Function Prototypes: */\r
                        #endif\r
 \r
                /* Inline Functions: */\r
-                       static inline void USB_REG_On(void) ATTR_ALWAYS_INLINE;\r
-                       static inline void USB_REG_On(void)\r
-                       {\r
-                               // TODO\r
-                       }\r
-\r
-                       static inline void USB_REG_Off(void) ATTR_ALWAYS_INLINE;\r
-                       static inline void USB_REG_Off(void)\r
-                       {\r
-                               // TODO\r
-                       }\r
-\r
-                       static inline void USB_CLK_Freeze(void) ATTR_ALWAYS_INLINE;\r
-                       static inline void USB_CLK_Freeze(void)\r
-                       {\r
-                               // TODO\r
-                       }\r
-\r
-                       static inline void USB_CLK_Unfreeze(void) ATTR_ALWAYS_INLINE;\r
-                       static inline void USB_CLK_Unfreeze(void)\r
-                       {\r
-                               // TODO\r
-                       }\r
-\r
                        static inline void USB_Controller_Enable(void) ATTR_ALWAYS_INLINE;\r
                        static inline void USB_Controller_Enable(void)\r
                        {\r
-                               // TODO\r
+                               USB.CTRLA |= (USB_ENABLE_bm | USB_STFRNUM_bm | USB_MAXEP_gm);\r
                        }\r
 \r
                        static inline void USB_Controller_Disable(void) ATTR_ALWAYS_INLINE;\r
                        static inline void USB_Controller_Disable(void)\r
                        {\r
-                               // TODO\r
+                               USB.CTRLA &= ~USB_ENABLE_bm;\r
                        }\r
 \r
                        static inline void USB_Controller_Reset(void) ATTR_ALWAYS_INLINE;\r
                        static inline void USB_Controller_Reset(void)\r
                        {\r
-                               // TODO\r
+                               USB.CTRLA &= ~USB_ENABLE_bm;\r
+                               USB.CTRLA |=  USB_ENABLE_bm;\r
                        }\r
 \r
        #endif\r