// Copyright 2021 XMOS LIMITED.
// This Software is subject to the terms of the XCORE VocalFusion Licence.

#ifndef __hid_report_descriptor_h__
#define __hid_report_descriptor_h__

#include "xua_hid_report.h"

#if 0
/* Existing static report descriptor kept for reference */
#ifdef HID_CONTROLS
unsigned char hidReportDescriptor[] =
{
    0x05, 0x0c,     /* Usage Page (Consumer Device) */
    0x09, 0x01,     /* Usage (Consumer Control) */
    0xa1, 0x01,     /* Collection (Application) */
#ifdef DFU_CONTROL_USB_HID
    0x85, 0x01,     // HID_BUTTON_REPORT_ID  // TODO: report ID uses the global definition
#endif
    0x15, 0x00,     /* Logical Minimum (0) */
    0x25, 0x01,     /* Logical Maximum (1) */
    0x09, 0xb0,     /* Usage (Play) */
    0x09, 0xb5,     /* Usage (Scan Next Track) */
    0x09, 0xb6,     /* Usage (Scan Previous Track) */
    0x09, 0xe9,     /* Usage (Volume Up) */
    0x09, 0xea,     /* Usage (Volume Down) */
    0x09, 0xe2,     /* Usage (Mute) */
    0x75, 0x01,     /* Report Size (1) */
    0x95, 0x06,     /* Report Count (6) */
    0x81, 0x02,     /* Input (Data, Var, Abs) */
    0x95, 0x02,     /* Report Count (2) */
    0x81, 0x01,     /* Input (Cnst, Ary, Abs) */
    0xc0            /* End collection */

#ifdef DFU_CONTROL_USB_HID
    ,0x06, 0x82, 0xff,
    0x09, 0x01,
    0xa1, 0x01,
    0x09, 0x03,
    0x85, 0x41,     // HID_DFU_REPORT_ID  // TODO: report ID uses the global definition
    0x15, 0x00,
    0x26, 0xff, 0x00,
    0x75, 0x08,
    0x95, 0x3f,
    0x81, 0x02,
    0x09, 0x04,
    0x15, 0x00,
    0x26, 0xff, 0x00,
    0x75, 0x08,
    0x95, 0x3f,
    0x91, 0x02,
    0xc0
#if 0
Usage Page (Vendor-Defined 131)	06 82 FF 
Usage (Vendor-Defined 1)	09 01 
Collection (Application)	A1 01 
    Usage (Vendor-Defined 3)	09 03 
    Report ID (65)	85 41 
    Logical Minimum (0)	15 00 
    Logical Maximum (255)	26 FF 00 
    Report Size (8)	75 08 
    Report Count (63)	95 3F 
    Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)	81 02 
    Usage (Vendor-Defined 4)	09 04 
    Logical Minimum (0)	15 00 
    Logical Maximum (255)	26 FF 00 
    Report Size (8)	75 08 
    Report Count (63)	95 3F 
    Output (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit)	91 02 
End Collection	C0 
#endif
#endif
};
#endif
#endif

/*
 * Define non-configurable items in the HID Report descriptor.
 */
static const USB_HID_Short_Item_t hidCollectionApplication  = {
    .header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_COLLECTION),
    .data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidCollectionApplication2  = {
    .header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_COLLECTION),
    .data = { 0x02, 0x00 } };

static const USB_HID_Short_Item_t hidCollectionEnd          = {
    .header = HID_REPORT_SET_HEADER(0, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_END_COLLECTION),
    .data = { 0x00, 0x00 } };

static const USB_HID_Short_Item_t hidInputConstArray        = {
    .header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_INPUT),
    .data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidInputDataVar           = {
    .header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_INPUT),
    .data = { 0x02, 0x00 } };

static const USB_HID_Short_Item_t hidInputFeatureVar           = {
    .header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_FEATURE),
    .data = { 0x01, 0x00 } };

static const USB_HID_Short_Item_t hidLogicalMaximum0        = {
    .header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM),
    .data = { 0x00, 0x00 } };
static const USB_HID_Short_Item_t hidLogicalMaximum1        = {
    .header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM),
    .data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidLogicalMinimum0        = {
    .header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MINIMUM),
    .data = { 0x00, 0x00 } };

static const USB_HID_Short_Item_t hidReportCount2           = {
    .header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
    .data = { 0x00, 0x00 } };
static const USB_HID_Short_Item_t hidReportCount8           = {
    .header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
    .data = { 0x08, 0x00 } };
static const USB_HID_Short_Item_t hidReportSize1            = {
    .header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_SIZE),
    .data = { 0x01, 0x00 } };

static const USB_HID_Short_Item_t hidUsageConsumerControl   = {
    .header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
    .data = { 0x01, 0x00 } };

static const USB_HID_Short_Item_t hidUsageConsumerControl2   = {
    .header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
    .data = { 0x02, 0x00 } };


/*
 * Define the HID Report Descriptor Item, Usage Page, Report ID and length for each HID Report
 * For internal purposes, a report element with ID of 0 must be included if report IDs are not being used.
 */
static const USB_HID_Report_Element_t hidReportPageConsumer = {
    .item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_USAGE_PAGE),
    .item.data = { USB_HID_USAGE_PAGE_ID_CONSUMER, 0x00 },
    .location = HID_REPORT_SET_LOC(0x1, 2, 0, 0 )
};

static const USB_HID_Report_Element_t hidReportPageVendor = {
    .item.header = HID_REPORT_SET_HEADER(2, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_USAGE_PAGE),
    .item.data = {0x83, 0xff },
    .location = HID_REPORT_SET_LOC(0x2, 2, 0, 0 )
};


static const USB_HID_Short_Item_t hidUsagePageConsumer      = { .header = 0x05, .data = { 0x0C, 0x00 }};

static const USB_HID_Short_Item_t hidUsagePageVendor        = { .header = 0x06, .data = { 0x82, 0xff }};

static const USB_HID_Short_Item_t hidUsageConsumerVendor    = { .header = 0x09, .data = { 0x03, 0x00 }};

static const USB_HID_Short_Item_t hidPassReportId            = { .header = 0x85, .data = { 0x1, 0x00 }};
static const USB_HID_Short_Item_t hidButtonReportId            = { .header = 0x85, .data = { 0x2, 0x00 }};

static const USB_HID_Short_Item_t hidLogicalMaximum2        = { .header = 0x26, .data = { 0xFF, 0x00 }};

static const USB_HID_Short_Item_t hidReportSize             = { .header = 0x75, .data = { 0x08, 0x00 }};
#if DEBUG_MEMORY_LOG_ENABLED
static const USB_HID_Short_Item_t hidPassReportCount            = { .header = 0x95, .data = { 0x3F, 0x00 }};
static const USB_HID_Short_Item_t hidPassReportCount2            = { .header = 0x95, .data = { 0x3F, 0x00 }};
static const USB_HID_Short_Item_t hidPassReportCount3            = { .header = 0x95, .data = { 0x3f, 0x00 }};
#else
static const USB_HID_Short_Item_t hidPassReportCount            = { .header = 0x95, .data = { 0x3f, 0x00 }};
static const USB_HID_Short_Item_t hidPassReportCount2            = { .header = 0x95, .data = { 0x3f, 0x00 }};
static const USB_HID_Short_Item_t hidPassReportCount3            = { .header = 0x95, .data = { 0x3f, 0x00 }};
#endif
static const USB_HID_Short_Item_t hidButtonReportCount           = { .header = 0x95, .data = { 0x04, 0x00 }};
static const USB_HID_Short_Item_t hidUsageVendor            = { .header = 0x09, .data = { 0x04, 0x00 }};
static const USB_HID_Short_Item_t hidUsageVendor2            = { .header = 0x09, .data = { 0x05, 0x00 }};
static const USB_HID_Short_Item_t hidOutputDataVar          = { .header = 0x91, .data = { 0x02, 0x00 }};

/*
 * Define configurable items in the HID Report descriptor.
 */

static USB_HID_Report_Element_t hidUsageByte0Bit7   = {
     .item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
     .item.data = { 0xE2, 0x00 },
     .location = HID_REPORT_SET_LOC(0, 0, 0, 5)
}; // Mute
static USB_HID_Report_Element_t hidUsageByte0Bit6   = {
     .item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
     .item.data = { 0xB4, 0x00 },
     .location = HID_REPORT_SET_LOC(0, 0, 0, 5)
}; // rewind
static USB_HID_Report_Element_t hidUsageByte0Bit5   = {
     .item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
     .item.data = { 0xB3, 0x00 },
     .location = HID_REPORT_SET_LOC(0, 0, 0, 5)
}; // forward
static USB_HID_Report_Element_t hidUsageByte0Bit4   = {
     .item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
     .item.data = { 0xB6, 0x00 },
     .location = HID_REPORT_SET_LOC(0, 0, 0, 2)
}; // Scan Prev
static USB_HID_Report_Element_t hidUsageByte0Bit3   = {
     .item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
     .item.data = { 0xB5, 0x00 },
     .location = HID_REPORT_SET_LOC(0, 0, 0, 1)
}; // Scan Next
static USB_HID_Report_Element_t hidUsageByte0Bit2   = {
     .item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
     .item.data = { 0xCD, 0x00 },
     .location = HID_REPORT_SET_LOC(0, 0, 0, 0)
}; // Play
static USB_HID_Report_Element_t hidUsageByte0Bit1   = {
     .item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
     .item.data = { 0xEA, 0x00 },
     .location = HID_REPORT_SET_LOC(0, 0, 0, 4)
}; // Vol-
static USB_HID_Report_Element_t hidUsageByte0Bit0   = {
     .item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
     .item.data = { 0xE9, 0x00 },
     .location = HID_REPORT_SET_LOC(0, 0, 0, 3)
}; // Vol+

/*
 * List the configurable elements in the HID Report descriptor.
 */
static USB_HID_Report_Element_t* const hidConfigurableElements[] = {
    &hidUsageByte0Bit0,
    &hidUsageByte0Bit1,
    &hidUsageByte0Bit2,
    &hidUsageByte0Bit3,
    &hidUsageByte0Bit4,
    &hidUsageByte0Bit5,
    &hidUsageByte0Bit6,
    &hidUsageByte0Bit7
};

/*
 * List HID Reports, one per Report ID. This should be a usage page item with the relevant
 * If not using report IDs - still have one with report ID 0
 */
static const USB_HID_Report_Element_t* const hidReports[] = {
    &hidReportPageVendor,
    &hidReportPageConsumer
};

/*
 * List all items in the HID Report descriptor.
 */
static const USB_HID_Short_Item_t* const hidReportDescriptorItems[] = {
    &(hidReportPageVendor.item),
    &hidUsageConsumerControl,
    &hidCollectionApplication,
            &hidUsageConsumerVendor,
            &hidPassReportId,
            &hidLogicalMinimum0,
            &hidLogicalMaximum2,
            &hidReportSize,
            &hidPassReportCount2,
            &hidInputDataVar,
            &hidUsageVendor,
            &hidLogicalMinimum0,
            &hidLogicalMaximum2,
            &hidReportSize,
            &hidPassReportCount,
            &hidOutputDataVar,
            &hidUsageVendor2,
            &hidReportSize,
            &hidPassReportCount3,
            &hidInputFeatureVar,
    &hidCollectionEnd,
    &(hidReportPageConsumer.item),
    &hidUsageConsumerControl,
    &hidCollectionApplication,
        &hidButtonReportId,
        &hidLogicalMinimum0,
        &hidLogicalMaximum1,
        &(hidUsageByte0Bit0.item),
        &(hidUsageByte0Bit1.item),
        &(hidUsageByte0Bit2.item),
        &(hidUsageByte0Bit3.item),
        &(hidUsageByte0Bit4.item),
        &(hidUsageByte0Bit5.item),
        &(hidUsageByte0Bit6.item),
        &(hidUsageByte0Bit7.item),
        &hidReportSize1,
        &hidReportCount8,
        &hidInputDataVar,
        &hidReportCount2,
        &hidInputConstArray,
    &hidCollectionEnd,
};

/*
 * Define the number of HID Reports
 * Due to XC not supporting designated initializers, this constant has a hard-coded value.
 * It must equal ( sizeof hidReports / sizeof ( USB_HID_Report_Element_t* ))
 */
#define HID_REPORT_COUNT ( 2 )

#endif // __hid_report_descriptor_h__
