///////////////////////////////////////////////////////////////////////////
///                          usb_desc_mouse.h                          ////
////                                                                   ////
//// An example set of device / configuration descriptors.             ////
//// This set works exclusively with ex_usb_mouse.c example.           ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////
////                                                                   ////
//// Version History:                                                  ////
////                                                                   ////
//// June 20th, 2005:                                                  ////
////  18Fxx5x Initial release.                                         ////
////                                                                   ////
//// May 13th, 2005:                                                   ////
////  Initial 18Fxx5x Beta.                                            ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////
////                                                                   ////
////  NOTE: DUE TO A LIMITATION OF THE WAY THIS CODE HANDLES MULTIPLE  ////
////        INTERFACES, ALL INTERFACES MUST START AT 0 AND BE          ////
////        SEQUENTIAL.  THEREFORE IF CONFIG 1 HAS 3 INTERFACES, THEY  ////
////        MUST BE INTERFACE 0, INTERFACE 1 and INTERFACE 2           ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2005 Custom Computer Services           ////
//// This source code may only be used by licensed users of the CCS    ////
//// C compiler.  This source code may only be distributed to other    ////
//// licensed users of the CCS C compiler.  No other use,              ////
//// reproduction or distribution is permitted without written         ////
//// permission.  Derivative programs created using this software      ////
//// in object code form are not restricted in any way.                ////
///////////////////////////////////////////////////////////////////////////

#IFNDEF __USB_DESCRIPTORS__
#DEFINE __USB_DESCRIPTORS__

#include <usb.h>

   //////////////////////////////////////////////////////////////////
   ///
   ///  HID Report.  Tells HID driver how to handle and deal with
   ///  received data.  HID Reports can be extremely complex,
   ///  see HID specifcation for help on writing your own.
   ///
   ///  First it defines a block for the first interface for a mouse
   ///  protocol.  Second it defines a block for the second interface
   ///  for a keyboard protocol.
   ///
   //////////////////////////////////////////////////////////////////

   const char USB_CLASS_SPECIFIC_DESC[] = {
    //hid report descriptor for interface 0 (joystick)
      0x05, 0x01,       // Usage Page = Generic Desktop                 ==0,1
      0x09, 0x04,       // Usage = Joystick                             ==2,3
      0xA1, 0x01,       // Collection = Application                     ==4,5
        0x09, 0x33,       // Usage (Rx)                                 ==6,7
        //0x79, 0x04,   //string index(4)                                            ==8,9
        0x09, 0x34,       // Usage (Ry)                                 ==8,9      ==10,11
        0x09, 0x35,       // Usage (Ry)                                 ==10,11    ==12,13
        0x09, 0x36,       // Usage (Slider)                             ==12,13    ==14,15
        0x15, 0x00,       // Logical  Minimum (0)                       ==14,15    ==16,17,
        0x26, 0xFF,0x03,  // Logical  Maximum (1023)                    ==16,17,18 ==18,19,20
        0x35, 0x00,       // Physical Minimum (0)                       ==19,20    ==21,22
        0x46, 0xFF,0x03,  // Physical Maximum (1023)                    ==21,22,23 ==23,24,25
        0x75, 0x0A,       // Report Size (10)  10 bits                  ==24,25    ==26,27
        0x95, 0x04,       // Report Count (4)                           ==26,27    ==28,29
        0x81, 0x02,       // Input (Data,Var,Abs)                       ==28,29    ==30,31
      0xC0,              // End Collection                              ==30       ==32

    //hid report descriptor for interface 1 (keyboard)
      0x05, 0x01, //usage page (generic desktop)                        ==31, 32   ==33
      0x09, 0x06, //usage (keyboard)                                    ==33, 34
      0xA1, 0x01, //collection (application)                            ==35, 36
        0x05, 0x07, //usage page (key codes)                            ==37, 38
        0x19, 0xE0, //usage min (224)                                   ==39, 40
        0x29, 0xE7, //usage max (231)                                   ==41, 42
        0x15, 0x00, //logical min (0)                                   ==43, 44
        0x25, 0x01, //logical max (1)                                   ==45, 46
        0x75, 0x01, //report size (1)                                   ==47, 48
        0x95, 0x08, //report count (8)                                  ==49, 50
        0x81, 0x02, //input (data, variable, absolute) [modifier byte]  ==51, 52
        0x95, 0x01, //report count (1)                                  ==53, 54
        0x75, 0x08, //report size (8)                                   ==55, 56
        0x81, 0x01, //input (constant) [reserved byte]                  ==57, 58
        0x95, 0x05, //report count (5)                                  ==59, 60
        0x75, 0x01, //report size (1)                                   ==61, 62
        0x05, 0x08, //usage page (page# for leds)                       ==63, 64
        0x19, 0x01, //usage min (1)                                     ==65, 66
        0x29, 0x05, //usage max (5)                                     ==67, 68
        0x91, 0x02, //output (data, var, abs) [led report]              ==69, 70
        0x95, 0x01, //report count (1)                                  ==71, 72
        0x75, 0x03, //report size (3)                                   ==73, 74
        0x91, 0x01, //output (constant) [led report padding]            ==75, 76
        0x95, 0x05, //report count (5)                                  ==77, 78
        0x75, 0x08, //report size (8)                                   ==79, 80
        0x15, 0x00, //logical min (0)                                   ==81, 82
        0x25, 0x65, //logical max (101)                                 ==83, 84
        0x05, 0x07, //usage page (key codes)                            ==85, 86
        0x19, 0x00, //usage min (0)                                     ==87, 88
        0x29, 0x65, //usage max (101)                                   ==89, 90
        0x81, 0x00, //input (data, array)                               ==91, 92
      0xC0        //end collection                                      ==93
   };

   //if a class has an extra descriptor not part of the config descriptor,
   // this lookup table defines where to look for it in the const
   // USB_CLASS_SPECIFIC_DESC[] array.
   //first element is the config number (if your device has more than one config)
   //second element is which interface number
   //set element to 0xFFFF if this config/interface combo doesn't exist
   const int16 USB_CLASS_SPECIFIC_DESC_LOOKUP[USB_NUM_CONFIGURATIONS][2] =
   {
   //config 1
      //interface 0
         0,
      //interface 1
         31 //33
   };

   //if a class has an extra descriptor not part of the config descriptor,
   // this lookup table defines the size of that descriptor.
   //first element is the config number (if your device has more than one config)
   //second element is which interface number
   //set element to 0xFFFF if this config/interface combo doesn't exist
   const int16 USB_CLASS_SPECIFIC_DESC_LOOKUP_SIZE[USB_NUM_CONFIGURATIONS][2] =
   {
   //config 1
      //interface 0
         33,//31,
      //interface 1
         63
   };

//////////////////////////////////////////////////////////////////
///
///   start config descriptor
///   right now we only support one configuration descriptor.
///   the config, interface, class, and endpoint goes into this array.
///
//////////////////////////////////////////////////////////////////

   #DEFINE USB_TOTAL_CONFIG_LEN      66 //config+interface+class+endpoint

   const char USB_CONFIG_DESC[] = {
   //IN ORDER TO COMPLY WITH WINDOWS HOSTS, THE ORDER OF THIS ARRAY MUST BE:
      //    config(s)
      //    interface(s)
      //    class(es)
      //    endpoint(s)

   //config_descriptor for config index 1
         USB_DESC_CONFIG_LEN, //length of descriptor size                        ==0
         USB_DESC_CONFIG_TYPE, //constant CONFIGURATION (CONFIGURATION 0x02)     ==1
         USB_TOTAL_CONFIG_LEN,0, //size of all data returned for this config     ==2,3
         2, //number of interfaces this device supports                          ==4
         0x01, //identifier for this configuration.  (IF we had more than one configurations)      ==5
         0x00, //index of string descriptor for this configuration               ==6
         0xC0, //bit 6=1 if self powered, bit 5=1 if supports remote wakeup (we don't), bits 0-4 unused and bit7=1         ==7
         0x32, //maximum bus power required (maximum milliamperes/2)  (0x32 = 100mA)   //8

   //interface descriptor 1 (HID)
         USB_DESC_INTERFACE_LEN, //length of descriptor      =9
         USB_DESC_INTERFACE_TYPE, //constant INTERFACE (INTERFACE 0x04)       =10
         0x00, //number defining this interface (IF we had more than one interface)    ==11
         0x00, //alternate setting     ==12
         1, //number of endpoints for this interface  //13
         0x03, //class code, 03 = HID     ==14
         0x00, //subclass code //boot     ==15
         0x00, //protocol code            ==16
         0x00, //index of string descriptor for interface      ==17

   //class descriptor 1  (HID)
         USB_DESC_CLASS_LEN, //length of descriptor    ==18
         USB_DESC_CLASS_TYPE, //dscriptor type (0x21 == HID)      ==19
         0x00,0x01, //hid class release number (1.0) (try 1.10)      ==20,21
         0x00, //localized country code (0 = none)       ==22
         0x01, //number of hid class descrptors that follow (1)      ==23
         0x22, //report descriptor type (0x22 == HID)                ==24
         USB_CLASS_SPECIFIC_DESC_LOOKUP_SIZE[0][0], 0x00, //length of report descriptor            ==25,26

   //endpoint descriptor 1
         USB_DESC_ENDPOINT_LEN, //length of descriptor                   ==27
         USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)          ==28
         0x81, //endpoint number and direction (0x81 = EP1 IN)       ==29
         USB_ENDPOINT_TYPE_INTERRUPT, //transfer type supported (0x03 is interrupt)         ==30
         USB_EP1_TX_SIZE,0x00, //maximum packet size supported                  ==31,32
         2,  //polling interval, in ms.  (cant be smaller than 10 for slow speed devices)  //10     ==33

   //interface descriptor 2 (KEYBOARD)
         USB_DESC_INTERFACE_LEN, //length of descriptor      =34
         USB_DESC_INTERFACE_TYPE, //constant INTERFACE (INTERFACE 0x04)       =35
         0x01, //number defining this interface (IF we had more than one interface)    ==36
         0x00, //alternate setting     ==37
         2, //number of endpoints for this interface  //38
         0x03, //class code, 03 = HID     ==39
         0x01, //subclass code //boot     ==40
         0x01, //protocol code (keyboard)      ==41
         0x00, //index of string descriptor for interface      ==42

   //class descriptor 2  (KEYBOARD)
         USB_DESC_CLASS_LEN, //length of descriptor    ==43
         USB_DESC_CLASS_TYPE, //dscriptor type (0x21 == HID)      ==44
         0x00,0x01, //hid class release number (1.0) (try 1.10)      ==45,46
         0x00, //localized country code (0 = none)       ==47
         0x01, //number of hid class descriptors that follow (1)      ==48
         0x22, //report descriptor type (0x22 == HID)                ==49
         USB_CLASS_SPECIFIC_DESC_LOOKUP_SIZE[0][1], 0x00, //length of report descriptor            ==50,51

   //endpoint descriptor 2 IN
         USB_DESC_ENDPOINT_LEN, //length of descriptor                   ==52
         USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)          ==53
         0x82, //endpoint number and direction (0x81 = EP1 IN)       ==54
         USB_ENDPOINT_TYPE_INTERRUPT, //transfer type supported (0x03 is interrupt)         ==55
         USB_EP2_TX_SIZE,0x00, //maximum packet size supported                  ==56,57
         10,  //polling interval, in ms.  (cant be smaller than 10 for slow speed devices)     ==58

   //endpoint descriptor 2 OUT
         USB_DESC_ENDPOINT_LEN, //length of descriptor                   ==52
         USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)          ==53
         0x02, //endpoint number and direction (0x81 = EP1 IN)       ==54
         USB_ENDPOINT_TYPE_INTERRUPT, //transfer type supported (0x03 is interrupt)         ==55
         USB_EP2_RX_SIZE,0x00, //maximum packet size supported                  ==56,57
         10  //polling interval, in ms.  (cant be smaller than 10 for slow speed devices)     ==58
   };



   //****** 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   2

   //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   2

   //define how many interfaces there are per config.  [0] is the first config, etc.
   const char USB_NUM_INTERFACES[USB_NUM_CONFIGURATIONS]={2};

   //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
   const int16 USB_CLASS_DESCRIPTORS[USB_NUM_CONFIGURATIONS][2][1]=
   {
   //config 1
      //interface 0
         //class 1
         18,
      //interface 1
         //class 1
         43
   };

   //****** END CONFIG DESCRIPTOR LOOKUP TABLES ********

   #if (sizeof(USB_CONFIG_DESC) != USB_TOTAL_CONFIG_LEN)
      #error USB_TOTAL_CONFIG_LEN not defined correctly
   #endif


//////////////////////////////////////////////////////////////////
///
///   start device descriptors
///
//////////////////////////////////////////////////////////////////

   const char USB_DEVICE_DESC[] = {
      //starts of with device configuration. only one possible
         USB_DESC_DEVICE_LEN, //the length of this report   ==1
         0x01, //the constant DEVICE (DEVICE 0x01)  ==2
         0x10,0x01, //usb version in bcd (pic167xx is 1.1) ==3,4
         0x00, //class code ==5
         0x00, //subclass code ==6
         0x00, //protocol code ==7
         USB_MAX_EP0_PACKET_LENGTH, //max packet size for endpoint 0. (SLOW SPEED SPECIFIES 8) ==8
         0x61,0x04, //vendor id (0x04D8 is Microchip, or is it 0x0461 ??)
         0x55,0x00, //product id   ==11,12  //don't use ffff says usb-by-example guy.  oops
         0x00,0x01, //device release number  ==13,14
         0x01, //index of string description of manufacturer. therefore we point to string_1 array (see below)  ==15
         0x02, //index of string descriptor of the product  ==16
         0x00, //index of string descriptor of serial number  ==17
         USB_NUM_CONFIGURATIONS  //number of possible configurations  ==18
   };

   #if (sizeof(USB_DEVICE_DESC) != USB_DESC_DEVICE_LEN)
      #error USB_DESC_DEVICE_LEN not defined correctly
   #endif


//////////////////////////////////////////////////////////////////
///
///   start string descriptors
///   String 0 is a special language string, and must be defined.  People in U.S.A. can leave this alone.
///
//////////////////////////////////////////////////////////////////

//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,22};

//number of strings you have, including string 0.
#define USB_STRING_DESC_COUNT sizeof(USB_STRING_DESC_OFFSET)


char const USB_STRING_DESC[]={
   //string 0
         4, //length of string index                                //0
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)      //1
         0x09, 0x04,   //Microsoft Defined for US-English           //2, 3
   //string 1
         18, //length of string index                               //4
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)      //5
         'N',0,                                                     //6,7
         '.',0,                                                     //8,9
         ' ',0,                                                     //10,11
         'C',0,                                                     //12,13
         'A',0,                                                     //14,15
         'M',0,                                                     //16,17
         'I',0,                                                     //18,19
         'L',0,                                                     //20, 21
   //string 2
         46, //length of string index                               //22
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)      //23
         'F',0,                                                     //24,25
         'A',0,                                                     //26,27
         'L',0,                                                     //28,29
         'C',0,                                                     //30,31
         'O',0,                                                     //32,33
         'N',0,                                                     //34,35
         '4',0,                                                     //36,37
         ' ',0,                                                     //38,39
         'I',0,                                                     //40,41
         'C',0,                                                     //42,43
         'P',0,                                                     //44,45
         ' ',0,                                                     //46,47
         'C',0,                                                     //48,49
         'o',0,                                                     //50,51
         'n',0,                                                     //52,53
         't',0,                                                     //54,55
         'r',0,                                                     //56,57
         'o',0,                                                     //58,59
         'l',0,                                                     //60,61
         'l',0,                                                     //62,63
         'e',0,                                                     //64,65
         'r',0,                                                     //66,67
   //string 3
         8, //length of string index                                //68,69
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)      //70
         'T',0,                                                     //72,73
         'W',0,                                                     //74,75
         '1',0                                                      //76,76
};
