#ifndef _usb_descriptors_h
#define _usb_descriptors_h

#define USBDESC __attribute__ ((section (".usb_desc")))

/*	Contains all the device, configuration, interface, endpoint, and string descriptor definitions
 *	The excellent breakdown of the USB standard and field comments have been copy pasted from the 
 *	almighty documentation "USB in a Nutshell" article by BeyondLogic: 
 *	http://www.beyondlogic.org/usbnutshell/usb5.shtml#DeviceDescriptors
 */
#define EP0_SIZE	0x08		//8Bytes same as usb 1.1 for now

#define	bLength			0		//offset of bLength in descriptor array
#define	bDescriptorType		1	//offset of bDescriptorType in descriptor array
#define	DESC_TYPE_MASK		0xFF00	//Descriptor type is upper byte of wValue
#define	DESC_IDX_MASK		0x00FF	//Descriptor index is lower byte of wValue
#define	DESC_TYPE_DEVICE 	0x01
#define	DESC_TYPE_CONFIG 	0x02
#define	DESC_TYPE_STRING 	0x03
#define	DESC_TYPE_INTERFACE 	0x04
#define	DESC_TYPE_ENDPOINT 	0x05

#define DEVICE_DESC_LEN	18
USBDESC const uint8_t device_desc[DEVICE_DESC_LEN] = {
// 0 	bLength 		1 	Number 		Size of the Descriptor in Bytes (18 bytes)
					DEVICE_DESC_LEN,
// 1 	bDescriptorType 	1 	Constant 	Device Descriptor (0x01)
					DESC_TYPE_DEVICE,
// 2 	bcdUSB 			2 	BCD 		USB Specification Number which device complies too.
					0x00, 0x02,
// 4 	bDeviceClass 		1 	Class 		Class Code (Assigned by USB Org) 
					0xFF,
// 							If equal to Zero, each interface specifies itÎéÎ÷s own class code 
// 							If equal to 0xFF, the class code is vendor specified.  
// 							Otherwise field is valid Class Code.
// 5 	bDeviceSubClass 	1 	SubClass 	Subclass Code (Assigned by USB Org)
					0x00,
// 6 	bDeviceProtocol 	1 	Protocol 	Protocol Code (Assigned by USB Org)
					0x00,
// 7 	bMaxPacketSize 		1 	Number 		Maximum Packet Size for Zero Endpoint. Valid Sizes are 8, 16, 32, 64 (for usb 2.0)
					EP0_SIZE,
// 8 	idVendor 		2 	ID 		Vendor ID (Assigned by USB Org)
					0xC0, 0x16,
// 10 	idProduct 		2 	ID 		Product ID (Assigned by Manufacturer)
					0xDC, 0x05,
// 12 	bcdDevice 		2 	BCD 		Device Release Number
					//0x00, 0x02,	early development version
					//0x01, 0x02,	//first public release 7SEP2018
					//0x02, 0x02,	//second public release 16NOV2018
					0x03, 0x02,	//third public release 30NOV2018
							//v2.3 is first to contain switchless USB firmware updates
							//application version numbers also included in this release
							//application version are meant to tack onto end of usb version
							//application version 0 is being released with this build
							//so we'll be at v2.3.0 application versions is expected to 
							//increment while maintaining usb/fwupater v2.3
							
// 14 	iManufacturer 		1 	Index 		Index of Manufacturer String Descriptor
					0x01,
// 15 	iProduct 		1 	Index 		Index of Product String Descriptor
					0x02,
// 16 	iSerialNumber 		1 	Index 		Index of Serial Number String Descriptor
					0x00,
// 17 	bNumConfigurations 	1 	Integer 	Number of Possible Configurations
					0x01 };


//	The bcdUSB field reports the highest version of USB the device supports. The value is in binary coded decimal 
//	with a format of 0xJJMN where JJ is the major version number, M is the minor version number and N is the sub minor 
//	version number. e.g. USB 2.0 is reported as 0x0200, USB 1.1 as 0x0110 and USB 1.0 as 0x0100.
//
//	The bDeviceClass, bDeviceSubClass and bDeviceProtocol are used by the operating system to find a class driver 
//	for your device. Typically only the bDeviceClass is set at the device level. Most class specifications choose to 
//	identify itself at the interface level and as a result set the bDeviceClass as 0x00. This allows for the one 
//	device to support multiple classes.
//
//	The bMaxPacketSize field reports the maximum packet size for endpoint zero. All devices must support endpoint zero.
//
//	The idVendor and idProduct are used by the operating system to find a driver for your device. The Vendor ID is assigned by the USB-IF.
//
//	The bcdDevice has the same format than the bcdUSB and is used to provide a device version number. This value is assigned by the developer.
//
//	Three string descriptors exist to provide details of the manufacturer, product and serial number. There is no 
//	requirement to have string descriptors. If no string descriptor is present, a index of zero should be used.
//
//	bNumConfigurations defines the number of configurations the device supports at its current speed.


//Configuration Descriptors
//
//    A USB device can have several different configurations although the majority of devices are simple and only have one. 
//    The configuration descriptor specifies how the device is powered, what the maximum power consumption is, the number of 
//    interfaces it has. Therefore it is possible to have two configurations, one for when the device is bus powered and another 
//    when it is mains powered. As this is a "header" to the Interface descriptors, its also feasible to have one configuration 
//    using a different transfer mode to that of another configuration.
//
//    Once all the configurations have been examined by the host, the host will send a SetConfiguration command with a non zero 
//    value which matches the bConfigurationValue of one of the configurations. This is used to select the desired configuration.
//
#define CONFIG_DESC_LEN		9	
#define INTERFACE_DESC_LEN 	9
#define ENDPOINT_DESC_LEN	0	//only describe EP's other than EP0
		//NOTE: current table broken if total is greater 255 bytes!!!
#define CONFIG_TOTAL_LEN	(CONFIG_DESC_LEN + INTERFACE_DESC_LEN + ENDPOINT_DESC_LEN)
#define	wTotalLength	2	//offset of wTotalLength in descriptor array
USBDESC const uint8_t config_desc[CONFIG_TOTAL_LEN] = {
// Off 	Field 			Size 	Value 		Description
// 0 	bLength 		1 	Number		Size of Descriptor in Bytes
					CONFIG_DESC_LEN,
// 1 	bDescriptorType 	1 	Constant 	Configuration Descriptor (0x02)
					DESC_TYPE_CONFIG,
// 2 	wTotalLength 		2 	Number		Total length in bytes of data returned
					CONFIG_TOTAL_LEN, 0x00,
// 4 	bNumInterfaces 		1 	Number		Number of Interfaces
					0x01,
// 5 	bConfigurationValue 	1 	Number		Value to use as an argument to select this configuration
					0x01,
// 6 	iConfiguration 		1 	Index		Index of String Descriptor describing this configuration
					0x00,
// 7 	bmAttributes 		1 	Bitmap		D7 Reserved, set to 1. (USB 1.0 Bus Powered)
//							D6 Self Powered
//							D5 Remote Wakeup
//							D4..0 Reserved, set to 0.
					0x80,
// 8 	bMaxPower 		1 	mA		Maximum Power Consumption in 2mA units
// 							bus powered devices should request more than 100mA
					100/2,
//
//	When the configuration descriptor is read, it returns the entire configuration hierarchy which includes all related 
//	interface and endpoint descriptors. The wTotalLength field reflects the number of bytes in the hierarchy.
//
//	bNumInterfaces specifies the number of interfaces present for this configuration.
//
//	bConfigurationValue is used by the SetConfiguration request to select this configuration.
//
//	iConfiguration is a index to a string descriptor describing the configuration in human readable form.
//
//	bmAttributes specify power parameters for the configuration. If a device is self powered, it sets D6. Bit D7 was used in 
//	USB 1.0 to indicate a bus powered device, but this is now done by bMaxPower. If a device uses any power from the bus, 
//	whether it be as a bus powered device or as a self powered device, it must report its power consumption in bMaxPower. 
//	Devices can also support remote wakeup which allows the device to wake up the host when the host is in suspend.
//
//	bMaxPower defines the maximum power the device will drain from the bus. This is in 2mA units, thus a maximum of 
//	approximately 500mA can be specified. The specification allows a high powered bus powered device to drain no more than 
//	500mA from Vbus. If a device loses external power, then it must not drain more than indicated in bMaxPower. It should 
//	fail any operation it cannot perform without external power.
//
//
//
//
//Interface Descriptors
//
//    The interface descriptor could be seen as a header or grouping of the endpoints into a functional group performing a 
//    single feature of the device. The interface descriptor conforms to the following format,
//
// Off 	Field 			Size 	Value 		Description
// 0 	bLength 		1 	Number		Size of Descriptor in Bytes (9 Bytes)
					INTERFACE_DESC_LEN,
// 1 	bDescriptorType 	1 	Constant	Interface Descriptor (0x04)
					DESC_TYPE_INTERFACE,
// 2 	bInterfaceNumber 	1 	Number		Number of Interface
					0x00,
// 3 	bAlternateSetting 	1 	Number		Value used to select alternative setting
					0x00,
// 4 	bNumEndpoints 		1 	Number		Number of Endpoints used for this interface
					0x00,
// 5 	bInterfaceClass 	1 	Class		Class Code (Assigned by USB Org)
					0x00,
// 6 	bInterfaceSubClass 	1 	SubClass	Subclass Code (Assigned by USB Org)
					0x00,
// 7 	bInterfaceProtocol 	1 	Protocol	Protocol Code (Assigned by USB Org)
					0x00,
// 8 	iInterface 		1 	Index		Index of String Descriptor Describing this interface
					0x00};
//
//	bInterfaceNumber indicates the index of the interface descriptor. This should be zero based, and incremented once 
//	for each new interface descriptor.
//
//	bAlternativeSetting can be used to specify alternative interfaces. These alternative interfaces can be selected 
//	with the Set Interface request.
//
//	bNumEndpoints indicates the number of endpoints used by the interface. This value should exclude endpoint zero 
//	and is used to indicate the number of endpoint descriptors to follow.
//
//	bInterfaceClass, bInterfaceSubClass and bInterfaceProtocol can be used to specify supported classes 
//	(e.g. HID, communications, mass storage etc.) This allows many devices to use class drivers preventing the 
//	need to write specific drivers for your device.
//
//	iInterface allows for a string description of the interface.
//
//Endpoint Descriptors
//
//    Endpoint descriptors are used to describe endpoints other than endpoint zero. Endpoint zero is always assumed to be a 
//    control endpoint and is configured before any descriptors are even requested. The host will use the information returned 
//    from these descriptors to determine the bandwidth requirements of the bus.
//
// Off 	Field 			Size 	Value 		Description
// 0 	bLength 		1 	Number		Size of Descriptor in Bytes (7 bytes)
// 1 	bDescriptorType 	1 	Constant	Endpoint Descriptor (0x05)
// 2 	bEndpointAddress 	1 	Endpoint 	Endpoint Address
//							  Bits 0..3b Endpoint Number.
//							  Bits 4..6b Reserved. Set to Zero
//							  Bits 7 Direction 0 = Out, 1 = In (Ignored for Control Endpoints)
// 3 	bmAttributes 		1 	Bitmap 		Bits 0..1 Transfer Type
//							  00 = Control 01 = Isochronous 10 = Bulk 11 = Interrupt
//							Bits 2..7 are reserved. If Isochronous endpoint,
//							Bits 3..2 = Synchronisation Type (Iso Mode)
//							  00 = No Synchonisation 01 = Asynchronous 10 = Adaptive 11 = Synchronous
//							Bits 5..4 = Usage Type (Iso Mode)
//							  00 = Data Endpoint 01 = Feedback Endpoint 
//							  10 = Explicit Feedback Data Endpoint 11 = Reserved
// 4 	wMaxPacketSize 		2 	Number		Maximum Packet Size this endpoint is capable of sending or receiving
// 6 	bInterval 		1 	Number		Interval for polling endpoint data transfers. Value in frame counts. 
// 							Ignored for Bulk & Control Endpoints. Isochronous must equal 1 and field may 
// 							range from 1 to 255 for interrupt endpoints.
//
//	bEndpointAddress indicates what endpoint this descriptor is describing.
//
//	bmAttributes specifies the transfer type. This can either be Control, Interrupt, Isochronous or Bulk Transfers. 
//	If an Isochronous endpoint is specified, additional attributes can be selected such as the Synchronisation and usage types.
//
//      wMaxPacketSize indicates the maximum payload size for this endpoint.
//
//      bInterval is used to specify the polling interval of certain transfers. The units are expressed in frames, 
//      thus this equates to either 1ms for low/full speed devices and 125us for high speed devices.
//                                                                                                                                                                                                        
//String Descriptors
//
//	String descriptors provide human readable information and are optional. If they are not used, any 
//	string index fields of descriptors must be set to zero indicating there is no string descriptor available.
//
//	The strings are encoded in the Unicode format and products can be made to support multiple languages. 
//	String Index 0 should return a list of supported languages. A list of USB Language IDs can be found in 
//	Universal Serial Bus Language Identifiers (LANGIDs) version 1.0
//
#define STRING0_DESC_LEN	4
USBDESC const uint8_t string0_desc[STRING0_DESC_LEN] = {
// Off 	Field 			Size 	Value 		Description
// 0 	bLength 		1 	Number		Size of Descriptor in Bytes
					STRING0_DESC_LEN,	
// 1 	bDescriptorType 	1 	Constant	String Descriptor (0x03)
					DESC_TYPE_STRING,
// 2 	wLANGID[0] 		2 	number		Supported Language Code Zero
//							(e.g. 0x0409 English - United States)
					0x09, 0x04};
// 4 	wLANGID[1] 		2 	number		Supported Language Code One
//							(e.g. 0x0c09 English - Australian)
// n 	wLANGID[x] 		2 	number		Supported Language Code x
//							(e.g. 0x0407 German - Standard)
//
//	The above String Descriptor shows the format of String Descriptor Zero. The host should read this descriptor to 
//	determine what languages are available. If a language is supported, it can then be referenced by sending the 
//	language ID in the wIndex field of a Get Descriptor(String) request.
//
//	All subsequent strings take on the format below,
//
// Off 	Field 			Size 	Value 		Description
// 0 	bLength 		1 	Number		Size of Descriptor in Bytes
// 1 	bDescriptorType 	1 	Constant	String Descriptor (0x03)
// 2 	bString 		n 	Unicode		Unicode Encoded String
//
//
//

//Defining string arrays as uint16_t effectively makes the strings UTF-16 as required
#define BYTES_PER_HWORD		2
#define STRING1_DESC_LEN	(21*BYTES_PER_HWORD)	//characters plus 1 for bLength & bDescriptorType
USBDESC const uint16_t string1_desc[STRING1_DESC_LEN] = {
// 0 	bLength 		1 	Number		Size of Descriptor in Bytes
// 1 	bDescriptorType 	1 	Constant	String Descriptor (0x03)
					((uint16_t)DESC_TYPE_STRING<<8 | STRING1_DESC_LEN),
// 2 	bString 		n 	Unicode		Unicode Encoded String
'I','n','f','i','n','i','t','e','N','e','s','L','i','v','e','s','.','c','o','m'};

#define STRING2_DESC_LEN	(15*BYTES_PER_HWORD)	//characters plus 1 for bLength & bDescriptorType
USBDESC const uint16_t string2_desc[STRING2_DESC_LEN] = {
// 0 	bLength 		1 	Number		Size of Descriptor in Bytes
// 1 	bDescriptorType 	1 	Constant	String Descriptor (0x03)
					((uint16_t)DESC_TYPE_STRING<<8 | STRING2_DESC_LEN),
// 2 	bString 		n 	Unicode		Unicode Encoded String
'I','N','L',' ','R','e','t','r','o','-','P','r','o','g'};

#endif
