//
#ifndef DESCRIPTORS
#define DESCRIPTORS

#define USB_REQTYPE_DIRECTION_MASK 0x80
#define USB_REQTYPE_TYPE_MASK 0x60
#define USB_REQTYPE_RECIPIENT_MASK 0x1F

#define USB_REQTYPE_STANDARD (0 << 5)
#define USB_REQTYPE_CLASS (1 << 5)
#define USB_REQTYPE_VENDOR (2 << 5)

#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef struct {
	__IO uint16_t ID;
	__IO uint16_t pageNumber;
	__IO uint16_t length;
	__IO uint16_t reserved;
} __attribute__ ((packed)) RECORD;
#endif

#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef	union {
	uint8_t array[256];
	RECORD structure[32];
} TABLE;
#endif

#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef struct {
		__IO uint8_t E;
		__IO uint8_t B;
		__IO uint8_t G;
		__IO uint8_t R;
} LED_COLOR;
#endif

#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
	__IO LED_COLOR TIMEFRAME_STRUCT[18];
	__IO uint8_t TIMEFRAME_ARRAY[72];
} LED_FRAME;
#endif

#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef	union {
	uint8_t array[7424];	//7206 used
	struct {
		__IO uint16_t ID;
		__IO uint16_t STEP;
		__IO uint8_t FNUM;
		__IO uint8_t DISCRETE;
		union {
			__IO uint8_t arrayFrame[7200];
			__IO LED_FRAME structFrame[100];	
			} FRAME;
		uint8_t reserved[218];
	} __attribute__ ((packed)) nonArray;
} LED_PATTERN;
#endif

#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
	uint32_t DESCADD:32;      
	} bit;                     
	uint32_t reg;                
}  USB_ADDR;
#endif

#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
	uint32_t  BYTE_COUNT:14;          
	uint32_t  MULTI_PACKET_SIZE:14;         
	uint32_t  SIZE:3;       
	uint32_t  AUTO_ZLP:1;     
	} bit;                      
	uint32_t reg;                
} USB_PCKSIZE;
#endif

#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
	struct {
		uint16_t  SUBPID:4;          
		uint16_t  VARIABLE:11;         
		uint16_t  :1;       
		} bit;                       
		uint16_t reg;                 
} USB_EXTREG;
#endif

#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
	struct {
		uint8_t  CRCERR:1;          
		uint8_t  ERRORFLOW:1;         
		uint8_t  :6;       
		} bit;                       /*!< Structure used for bit  access                  */
		uint8_t reg;                 /*!< Type      used for register access              */
	} USB_STATUS_BK;
#endif

struct {
	__IO USB_ADDR ADDR;
	__IO USB_PCKSIZE PCKSIZE;
	__IO USB_EXTREG EXTREG;
	__IO USB_STATUS_BK STATUS_BK;
	uint8_t Reserved[5];
} __attribute__ ((packed)) nonArray;

#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef	union {
	__attribute__((aligned(4))) uint32_t array[4];
	struct {
		__IO USB_ADDR ADDR;
		__IO USB_PCKSIZE PCKSIZE;
		__IO USB_EXTREG EXTREG;
		__IO USB_STATUS_BK STATUS_BK;
		uint8_t Reserved[5];
	} __attribute__ ((packed)) nonArray;
} USB_DescriptorBank;
#endif

#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))		
typedef struct {
	USB_DescriptorBank Bank[2];
} USB_Endpoint;
#endif

typedef union {
	__attribute__((aligned(4))) uint32_t u32[16];
	uint8_t u8[64];
} USB_EndpointData;
				
typedef struct {
	uint8_t bLength;
	uint8_t bDescriptorType;
	uint16_t bcdUSB;
	uint8_t bDeviceClass;
	uint8_t bDeviceSubClass;
	uint8_t bDeviceProtocol;
	uint8_t bMaxPacketSize0;
	uint16_t idVendor;
	uint16_t idProduct;
	uint16_t bcdDevice;
	uint8_t iManufacturer;
	uint8_t iProduct;
	uint8_t iSerialNumber;
	uint8_t bNumConfiguration;
} __attribute__ ((packed)) deviceDescriptor;

typedef union {
	uint8_t reg;
	struct {
		uint8_t reserved:5;
		uint8_t remoteWU:1;
		uint8_t sPow:1;
		uint8_t bPow:1;
	} bit;
} bmAttribute;

typedef struct {
	uint8_t bLength;
	uint8_t bDescriptorType;
	uint16_t wTotalLength;
	uint8_t bNumInterfaces;
	uint8_t bConfigurationValue;
	uint8_t iConfiguration;
	bmAttribute bmAttributes;
	uint8_t bMaxPower;
} __attribute__ ((packed)) configurationDescriptor;

typedef struct{
	uint8_t reserved:6;	
	uint8_t remoteWU:1;
	uint8_t bPowered:1;
} __attribute__((packed)) epStatus;

typedef struct {
	uint8_t bLength;
	uint8_t bDescriptorType;
	uint8_t bInterfaceNumber;
	uint8_t bAlternateSetting;
	uint8_t bNumEndpoints;
	uint8_t bInterfaceClass;
	uint8_t bInterfaceSubClass;
	uint8_t bInterfaceProtocol;
	uint8_t iInterface;
} __attribute__ ((packed)) interfaceDescriptor;

typedef struct {
	uint8_t bLength;
	uint8_t bDescriptorType;
	uint16_t bcdHID;
	uint8_t bCountryCode;
	uint8_t bNumDescriptors;
	uint8_t wDescriptorType;
	uint16_t wDescriptorLength;
} __attribute__ ((packed)) hidDescriptor;

typedef struct {
	uint8_t bLength;
	uint8_t bDescriptorType;
	uint8_t bEndpointAddress;
	uint8_t bmAttributes;
	uint16_t wMaxPacketSize;
	uint8_t bInterval;
} __attribute__ ((packed)) endpointDescriptor;

uint8_t reportDescriptor0[] = {
	0x05, 0x01,	//Usage Page(Generic Desktop)
	0x09, 0x07,	//Usage(Keyboard)
	0x95, 0x00, //Report Count(0)
	0xA1, 0x01, //Collection(Application)
	0x05, 0x07,	//Usage Page(Key Codes)
	0x19, 0x00, //Usage Minimum(53h)
	0x29, 0x63, //Usage Maximum(63h)
	0x15, 0x00, //Logical Minimum(0)
	0x25, 0x63, //Logical Maximum(17)
	0x75, 0x08, //Report Size(8)
	0x95, 0x04, //Report Count(4)
	0x81, 0x00, //Input(Data, Array)
	0xC0 //EndCollection
};

uint8_t reportDescriptor1[] = {
	0x06, 0x00, 0xFF,	//Usage Page(vendor defined)
	0x09, 0x01, // Local   Usage (vendor usage 1)
	0xA1, 0x01, //Collection(Application)
	0x15, 0x00, //Logical Minimum(0)
	0x26, 0xFF, 0x00,	//Logical Maximum(255)
	0x75, 0x08, //Report Size(8)
	
	0x85, 0x01,	//Report ID(1)
	0x95, 0x08, //Report Count(3)
	0x19, 0x00,			//Usage minimum(0)
	0x2A, 0xFF, 0x00,	//Usage maximum(255)
	0x09, 0x01, // Local   Usage (vendor usage 1)
	0x91, 0x02, //Output(Data, Array)
	
	0x85, 0x02,	//Report ID(2)
	0x95, 0x26, //Report Count(38)
	0x19, 0x00,			//Usage minimum(0)
	0x2A, 0xFF, 0x00,	//Usage maximum(255)
	0x09, 0x01, // Local   Usage (vendor usage 1)
	0x91, 0x02, //Output(Data, Array)
	
	0x85, 0x03,	//Report ID(3)
	0x95, 0x08, //Report Count(8)
	0x19, 0x00,			//Usage minimum(0)
	0x2A, 0xFF, 0x00,	//Usage maximum(255)
	0x09, 0x01, // Local   Usage (vendor usage 1)
	0x91, 0x02, //Output(Data, Array)
	
	0xC0 //EndCollection
};

//0x01 0x02 0x00
deviceDescriptor devDesc = {0x12, 0x01, 0x0200, 0x00, 0x00, 0x00, 0x40, 0x046D, 0xC221, 0x0170, 0x00, 0x00, 0x00, 0x01};
configurationDescriptor confDesc = {0x09, 0x02, 0x003B, 0x02, 0x01, 0x00, {0x50}, 0x32};
interfaceDescriptor intDesc0 = {0x09, 0x04, 0x00, 0x00, 0x01, 0x03, 0x01, 0x01, 0x00};
hidDescriptor hidDesc0 = {0x09, 0x21, 0x0111, 0x00, 0x01, 0x22, 0x0019}; //DO reportDescLength 0x0040
endpointDescriptor endpointDesc0 = {0x07, 0x05, 0x00, 0x00, 0x0020, 0x01};
endpointDescriptor endpointDesc1 = {0x07, 0x05, 0x81, 0x03, 0x0008, 0x01};
interfaceDescriptor intDesc1 = {0x09, 0x04, 0x01, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00};
hidDescriptor hidDesc1 = {0x09, 0x21, 0x0111, 0x00, 0x01, 0x22, 0x0036};
endpointDescriptor endpointDesc2 = {0x07, 0x05, 0x02, 0x03, 0x0040, 0x01};

USB_EndpointData EP0OUT;
USB_EndpointData EP0IN;
USB_EndpointData EP2OUT;
USB_EndpointData EP1IN;

USB_Endpoint EP[3];

typedef uint32_t io_buffer __attribute__((__aligned__(4)));

typedef union {
	uint16_t array[4];
	struct {
	uint8_t bmRequestType;
	uint8_t bRequest;
	uint16_t wValue;
	uint16_t wIndex;
	uint16_t wLength;
	} nonArray;
} __attribute__ ((packed)) USB_SetupPacket;

enum {
	USB_REQ_GetStatus = 0,
	USB_REQ_ClearFeature = 1,
	USB_REQ_SetFeature = 3,
	USB_REQ_SetAddress = 5,
	USB_REQ_GetDescriptor = 6,
	USB_REQ_SetDescriptor = 7,
	USB_REQ_GetConfiguration = 8,
	USB_REQ_SetConfiguration = 9,
	USB_REQ_GetInterface = 10,
	USB_REQ_SetInterface = 11,
	USB_REQ_SynchFrame = 12,
};

enum {
	USB_REQ_GetReport = 1,
	USB_REQ_GetIdle = 2,
	USB_REQ_GetProtocol = 3,
	USB_REQ_SetReport = 9,
	USB_REQ_SetIdle = 10,
	USB_REQ_SetProtocol = 11,
};

enum {
	USB_DTYPE_Device = 0x01,
	USB_DTYPE_Configuration = 0x02,
	USB_DTYPE_String = 0x03,
	USB_DTYPE_Interface = 0x04,
	USB_DTYPE_Endpoint = 0x05,
	USB_DTYPE_DeviceQualifier = 0x06,
	USB_DTYPE_Other = 0x07,
	USB_DTYPE_InterfacePower = 0x08,
	USB_DTYPE_InterfaceAssociation = 0x0B,
	USB_DTYPE_HID = 0x21,
	USB_DTYPE_CSInterface = 0x24,
	USB_DTYPE_CSEndpoint = 0x25,
	USB_DTYPE_Report = 0x22,
} USB_dtype;

#ifdef __GNUC__
#define SECTION_USB_DESCRIPTOR       __attribute__ ((section(".hsram")))
#elif defined(__ICCARM__)
#define SECTION_USB_DESCRIPTOR       @".hsram"
#endif
// 
// #if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
// typedef union {
// 	UsbDevice                 DEVICE;      /**< \brief Offset: 0x000 USB is Device */
// 	UsbHost                   HOST;        /**< \brief Offset: 0x000 USB is Host */
// } Usb;
// #endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) 

/*@}*/

#endif /* _SAML21_USB_COMPONENT_ */
