#IFNDEF __USB_DESCRIPTORS__
#DEFINE __USB_DESCRIPTORS__

#include <usb.h>

//custom defines

   // 1 to stay compatible to USB MIDI spec, 0 as workaround for some windows versions...
   #define USE_AC_INTERFACE   0
   #define CS_INTERFACE   0x24   // Class-specific type: Interface
   #define CS_ENDPOINT   0x25   // Class-specific type: Endpoint

//////////////////////////////////////////////////////////////////
///
///   start config descriptor
///   right now we only support one configuration descriptor.
///   the config, interface, class, and endpoint goes into this array.
///
//////////////////////////////////////////////////////////////////

	#if USE_AC_INTERFACE
		#DEFINE USB_TOTAL_CONFIG_LEN	9+9+9+9+7+6+6+9+9+7+5+7+5	//config+interface+class+endpoint
	#else
		#DEFINE USB_TOTAL_CONFIG_LEN	9+9+7+6+6+9+9+7+5+7+5 	//config+interface+class+endpoint
	#endif
	
	#define CS_TOTAL_SIZE 7+6+6+9+9+7+5+7+5
	#if (CS_TOTAL_SIZE != 0x3D)
    	#error CS_TOTAL_SIZE not defined correctly
	#endif
   

//configuration descriptor
char const USB_CONFIG_DESC[] = {
	//config_descriptor for config index 1
		USB_DESC_CONFIG_LEN,       //length of descriptor size
		USB_DESC_CONFIG_TYPE,      //constant CONFIGURATION (0x02)
		USB_TOTAL_CONFIG_LEN,
		0,    //size of all data returned for this config
	#if USE_AC_INTERFACE
		0x02,            // Number of interfaces
	#else
		0x01,            // Number of interfaces
	#endif
		0x01,                      //identifier for this configuration.  (IF we had more than one configurations)
		0x00,                      //index of string descriptor for this configuration
		0x80,                      //bus powered //bit 6=1 if self powered, bit 5=1 if supports remote wakeup (we don't), bits 0-4 reserved and bit7=1
		0x32,                      //maximum bus power required (maximum milliamperes/2)  (0x10 = 32mA)
		
	#if USE_AC_INTERFACE
	// Standard AC Interface Descriptor
		USB_DESC_INTERFACE_LEN,            // Descriptor length
		USB_DESC_INTERFACE_TYPE,         // Descriptor type
		0x00,            // Zero-based index of this interface
		0x00,            // Alternate setting
		0x00,            // Number of end points 
		0x01,            // Interface class  (AUDIO)
		0x01,            // Interface sub class  (AUDIO_CONTROL)
		0x00,            // Interface sub sub class
		0x01,            // Interface descriptor string index
		
	// MIDI Adapter Class-specific AC Interface Descriptor
		9,            // Descriptor length
		CS_INTERFACE,         // Descriptor type
		0x01,            // subtype
		0x00,            // Revision of class specification - 1.0 (LSB)
		0x01,            // Revision of class specification (MSB)
		9,            // Total size of class-specific descriptors (LSB)
		0,            // Total size of class-specific descriptors (MSB)
		0x01,            // Number of streaming interfaces
		0x01,            // MIDI Streaming Interface 1 belongs to this AudioControl Interface
	#endif
		
	// Standard MS Interface Descriptor
		USB_DESC_INTERFACE_LEN,     // Descriptor length
		USB_DESC_INTERFACE_TYPE,    // Descriptor type
	#if USE_AC_INTERFACE
		0x01,            // Zero-based index of this interface
	#else
		0x00,            // Zero-based index of this interface
	#endif
		0x00,            // Alternate setting
		0x02,            // Number of end points 
		0x01,            // Interface class  (AUDIO)
		0x03,            // Interface sub class  (MIDISTREAMING)
		0x00,            // Interface sub sub class
		0x00,            // Interface descriptor string index
		
	// Class-specific MS Interface Descriptor
		7,            // Descriptor length
		CS_INTERFACE,         // Descriptor type
	/*#if USE_AC_INTERFACE
		0x01,            // Zero-based index of this interface
	#else
		0x00,            // Zero-based index of this interface
	#endif*/
		0x01, //MS_HEADER subtype
		0x00,            // revision of this class specification (LSB)
		0x01,            // revision of this class specification (MSB)
		CS_TOTAL_SIZE,// Total size of class-specific descriptors (LSB)
		0,            // Total size of class-specific descriptors (MSB)
		
	// MIDI IN Jack Descriptor (Embedded)
		6,            // Descriptor length
		CS_INTERFACE,         // Descriptor type (CS_INTERFACE)
		0x02,            // MIDI_IN_JACK subtype
		0x01,            // EMBEDDED
		0x01,            // ID of this jack
		0x00,            // unused
		
	// MIDI Adapter MIDI IN Jack Descriptor (External)
		6,            // Descriptor length
		CS_INTERFACE,         // Descriptor type (CS_INTERFACE)
		0x02,            // MIDI_IN_JACK subtype
		0x02,            // EXTERNAL
		0x02,            // ID of this jack
		0x00,            // unused
		
	// MIDI Adapter MIDI OUT Jack Descriptor (Embedded)
		9,            // Descriptor length
		CS_INTERFACE,         // Descriptor type (CS_INTERFACE)
		0x03,            // MIDI_OUT_JACK subtype
		0x01,            // EMBEDDED
		0x03,            // ID of this jack
		0x01,            // number of input pins of this jack
		0x02,            // ID of the entity to which this pin is connected
		0x01,            // Output Pin number of the entity to which this input pin is connected
		0x00,            // unused
		
	// MIDI Adapter MIDI OUT Jack Descriptor (External)
		9,            // Descriptor length
		CS_INTERFACE,         // Descriptor type (CS_INTERFACE)
		0x03,            // MIDI_OUT_JACK subtype
		0x02,            // EXTERNAL
		0x04,            // ID of this jack
		0x01,            // number of input pins of this jack
		0x01,//WAS:2            // ID of the entity to which this pin is connected
		0x01,            // Output Pin number of the entity to which this input pin is connected
		0x00,            // unused
		
	// Standard Bulk IN Endpoint Descriptor
		USB_DESC_ENDPOINT_LEN,            // Descriptor length
		USB_DESC_ENDPOINT_TYPE,         // Descriptor type
		0x81,//WAS:82            // In Endpoint 2
		0x02,            // Bulk, not shared
		USB_EP1_TX_SIZE,            // 64 bytes per packet (LSB)
		0x00,            // bytes per packet (MSB)
		0x00,            // ignore for bulk
		//0x00,            // unused
		//0x00,            // unused
		
	// Class-specific MS Bulk In Endpoint Descriptor
		5,//4+NUMBER_MIDI_INTERFACES,   // Descriptor length
		CS_ENDPOINT,         // Descriptor type (CS_ENDPOINT)
		0x01,            // MS_GENERAL
		1,   // number of embedded MIDI Out Jacks
		0x03,            // ID of embedded MIDI Out Jack
		
	// Standard Bulk OUT Endpoint Descriptor
		USB_DESC_ENDPOINT_LEN,            // Descriptor length
		USB_DESC_ENDPOINT_TYPE,         // Descriptor type
		0x02,            // Out Endpoint 2
		0x02,            // Bulk, not shared
		USB_EP2_RX_SIZE,            // 8 bytes per packet (LSB) --- to slow down transfers!
		0x00,            // bytes per packet (MSB)
		0x00,            // ignore for bulk
		//0x00,            // unused
		//0x00,            // unused
		
	// Class-specific MS Bulk Out Endpoint Descriptor
		5,//4+NUMBER_MIDI_INTERFACES,   // Descriptor length
		CS_ENDPOINT,         // Descriptor type (CS_ENDPOINT)
		0x01,            // MS_GENERAL
		1,   // number of embedded MIDI IN Jacks
		0x01            // ID of embedded MIDI In Jack
};
		
	//****** BEGIN CONFIG DESCRIPTOR LOOKUP TABLES ********
	//since we can't make pointers to constants in certain pic16s, this is an offset table to find
	//  a specific descriptor in the above table.
	
	//NOTE: DO TO A LIMITATION OF THE CCS CODE, ALL HID INTERFACES MUST START AT 0 AND BE SEQUENTIAL
	//      FOR EXAMPLE, IF YOU HAVE 2 HID INTERFACES THEY MUST BE INTERFACE 0 AND INTERFACE 1
	#define USB_NUM_HID_INTERFACES   0
	
	//the maximum number of interfaces seen on any config
	//for example, if config 1 has 1 interface and config 2 has 2 interfaces you must define this as 2
	#define USB_MAX_NUM_INTERFACES   1
	
	//define how many interfaces there are per config.  [0] is the first config, etc.
	const char USB_NUM_INTERFACES[USB_NUM_CONFIGURATIONS]={1};
	
	#if (sizeof(USB_CONFIG_DESC) != USB_TOTAL_CONFIG_LEN)
		#error USB_TOTAL_CONFIG_LEN not defined correctly
	#endif

	//define where to find class descriptors
	//first dimension is the config number
	//second dimension specifies which interface
	//last dimension specifies which class in this interface to get, but most will only have 1 class per interface
	//if a class descriptor is not valid, set the value to 0xFFFF
	#define CS_COUNT 3
	#define CS_POS_1 18
	#define CS_POS_2 18+7+6+6+9+9+7
	#define CS_POS_3 18+7+6+6+9+9+7+5+7                                       
	const int16 USB_CLASS_DESCRIPTORS[USB_NUM_CONFIGURATIONS][USB_MAX_NUM_INTERFACES][3]=
	{
		//config 1
			//interface 0
				//class 1
				CS_POS_1, /*9+18+9+7,9+9+7+6,9+18+9+7+6+6,9+18+9+7+6+6+9,*/ CS_POS_2, CS_POS_3
	};

//////////////////////////////////////////////////////////////////
///
///   start device descriptors
///
//////////////////////////////////////////////////////////////////

   //device descriptor
   char const USB_DEVICE_DESC[] ={
         USB_DESC_DEVICE_LEN,          //the length of this report
         0x01,                //constant DEVICE (0x01)
         0x10,0x01,           //usb version in bcd
         0x00,                //class code (if 0, interface defines class.  FF is vendor defined)
         0x00,                //subclass code
         0x00,                //protocol code
         USB_MAX_EP0_PACKET_LENGTH,   //max packet size for endpoint 0. (SLOW SPEED SPECIFIES 8)
         0x61,0x04,           //vendor id (0x04D8 is Microchip)
         0x04,0x00,           //product id
         0x00,0x01,           //device release number
         0x01,                //index of string description of manufacturer. therefore we point to string_1 array (see below)
         0x02,                //index of string descriptor of the product
         0x00,                //index of string descriptor of serial number
         USB_NUM_CONFIGURATIONS   //number of possible configurations
   };


//////////////////////////////////////////////////////////////////
///
///   start string descriptors
///   String 0 is a special language string, and must be defined.  People in U.S.A. can leave this alone.
///
///   You must define the length else get_next_string_character() will not see the string
///   Current code only supports 10 strings (0 thru 9)
///
//////////////////////////////////////////////////////////////////

//the offset of the starting location of each string.
//offset[0] is the start of string 0, offset[1] is the start of string 1, etc.
const char USB_STRING_DESC_OFFSET[]={0,4,12};

#define USB_STRING_DESC_COUNT sizeof(USB_STRING_DESC_OFFSET)

char const USB_STRING_DESC[]={
   //string 0
         4, //length of string index
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
         0x09,0x04,   //Microsoft Defined for US-English
   //string 1
         8, //length of string index
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
         'S',0,
         'P',0,
         'V',0,
   //string 2
         28, //length of string index
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
         'S',0,
         'P',0,
         'V',0,
         ' ',0,
         'M',0,
         'i',0,
         'd',0,
         'i',0,
         ' ',0,
         'D',0,
         'J',0,
         ' ',0,
         ' ',0
};


#ENDIF
