#ifndef USBAudio1_h
#define USBAudio1_h

#include "usb.h"

/*
 * Class, SubClass, Protocol (CSP) values
 */
#define USB_AUDIO_CONTROL_SUBCLASS      1
#define USB_AUDIO_STREAMING_SUBCLASS    2
#define USB_AUDIO_CS_CONTROL            0x10100
#define USB_AUDIO_CS_STREAMING          0x10200

/*
 * Extension to Standard Endpoint Descriptor
 */
typedef __packed struct
{
    USB_EndpointDescriptor      base;
    uint8_t                     bRefresh;
    uint8_t                     bSynchAddress;
} USBAudio_ST_EndpointDescriptor;

/*
 * Audio Control Interface (CI) descriptor subtypes
 */
#define USB_AUDIO_CI_UNDEFINED          0

typedef __packed struct
{
    USB_DescriptorSubBase;
                #define USB_AUDIO_CI_HEADER             1
    uint16_t            bcdADC;             // Revision of class specification
    uint16_t            wTotalLength;       // Total size of class specific descriptors
    uint8_t             bInCollection;      // Number of streaming interfaces
    uint8_t             baInterfaceNr[];    // index = interface number -1
} USBAudio_CI_Header;

#define USB_AUDIO_CI_TT_USB_STREAMING       0x101
#define USB_AUDIO_CI_TT_MICROPHONE          0x201

typedef __packed struct
{
    USB_DescriptorSubBase;
                #define USB_AUDIO_CI_INPUT_TERMINAL     2
    uint8_t             bTerminalID;        // ID of this input terminal
    uint16_t            wTerminalType;      
    uint8_t             bAssocTerminal;
    uint8_t             bNrChannels;
    uint16_t            wChannelConfig;
    uint8_t             iChannelNames;
    uint8_t             iTerminal;
} USBAudio_CI_InputTerminal;

typedef __packed struct
{
    USB_DescriptorSubBase;
                #define USB_AUDIO_CI_OUTPUT_TERMINAL    3
    uint8_t             bTerminalID;
    uint16_t            wTerminalType;
    uint8_t             bAssocTerminal;
    uint8_t             bSourceID;
    uint8_t             iTerminal;
} USBAudio_CI_OutputTerminal;

/*******************************************************************************
 * USBAudio_CI_MixerUnit is split into 3 parts because of variable length fields.
 * MACROS are included to access the other parts from the USBAudio_CI_MixerUnit*
 */

typedef __packed struct
{
    USB_DescriptorSubBase;
                #define USB_AUDIO_CI_MIXER_UNIT         4
    uint8_t             bUnitID;
    uint8_t             bNrInPins;
    uint8_t             baSourceID[];
} USBAudio_CI_MixerUnit;


typedef __packed struct
{
    uint8_t             bNrChannels;
    uint16_t            wChannelConfig;
    uint8_t             iChannelNames;
    uint8_t             bmControls[];
} USBAudio_CI_MixerUnitPart2;

typedef __packed struct
{
    uint8_t             iMixer;
} USBAudio_CI_MixerUnitPart3;


// sizeof(bmControls)
#define USBAudio_CI_sizeof_mu_controls(mixu) ((mixu)->bLength - 10 - (mixu)->bNrInPins)

// Equivalent to: USBAudio_CI_MixerUnitPart2* USBAudio_CI_MixerUnit2(USBAudio_CI_MixerUnit*)
#define USBAudio_CI_MixerUnit2(mixu) ((USBAudio_CI_MixerUnitPart2*)(&(mixu)->baSourceID[(mixu)->bNrInPins]))

// Equivalent to: USBAudio_CI_MixerUnitPart3* USBAudio_CI_MixerUnit2(USBAudio_controlMixerUnit*)
#define USBAudio_CI_MixerUnit3(mixu) ((USBAudio_CI_MixerUnitPart3*)(((char*)mixu))+\
                                                 (mixu)->bLength-sizeof(USBAudio_CI_MixerUnitPart3))

/*******************************************************************************
 * USBAudio_CI_SelectorUnit is split into 2 parts because of variable length fields.
 * MACROS are included to access the other parts from the USBAudio_CI_SelectorUnit*
 */


typedef __packed struct
{
    USB_DescriptorSubBase;
                #define USB_AUDIO_CI_SELECTOR_UNIT      5
    uint8_t             bUnitID;
    uint8_t             bNrInPins;
    uint8_t             baSourceID[];
} USBAudio_CI_SelectorUnit;

typedef __packed struct
{
    uint8_t             iSelector;
} USBAudio_CI_SelectorUnitPart2;

#define USBAudio_CI_sizeof_su_controls(mixu) ((su)->bLength - 6 - (su)->bNrInPins)

// Equivalent to: USBAudio_CI_SelectorUnitPart2* USBAudio_CI_SelectorUnit2(USBAudio_CI_SelectorUnit*)
#define USBAudio_CI_SelectorUnit2(su) ((USBAudio_CI_SelectorUnitPart2*)(&(su)->baSourceID[(su)->bNrInPins]))



/*******************************************************************************
 * USBAudio_CI_FeatureUnit is split into 2 parts because of variable length fields.
 * MACROS are included to access the other parts from the USBAudio_CI_FeatureUnit*
 */


typedef __packed struct
{
    USB_DescriptorSubBase;
                #define USB_AUDIO_CI_FEATURE_UNIT       6
    uint8_t             bUnitID;
    uint8_t             bSourceID;
    uint8_t             bControlSize;
    uint8_t             bmaControls[];
} USBAudio_CI_FeatureUnit;

typedef __packed struct
{
    uint8_t             iFeature;
} USBAudio_CI_FeatureUnitPart2;

// sizeof(bmControls)
#define USBAudio_CI_sizeof_fu_controls(fu) ((fu)->bLength - 7)

// Equivalent to: USBAudio_CI_FeatureUnitPart2* USBAudio_CI_FeatureUnit2(USBAudio_CI_FeatureUnit*)
#define USBAudio_CI_FeatureUnit2(fu) ((USBAudio_CI_FeatureUnitPart2*)(((char*)fu) + \
                                              fu->bLength-sizeof(USBAudio_CI_FeatureUnitPart2)))


//*******************************************************************************

    #define USB_AUDIO_CI_PROCESSING_UNIT    7
        /*
         * Processing Unit (PU) wProcessType type
         */
        #define USB_AUDIO_PU_UNDEFINED          0
        #define USB_AUDIO_PU_UP_DOWN_MIX        1
        #define USB_AUDIO_PU_DOLBY_PROLOGIC     2
        #define USB_AUDIO_PU_STEREO_EXTENDER    3
        #define USB_AUDIO_PU_REVERBERATION      4
        #define USB_AUDIO_PU_CHORUS             5
        #define USB_AUDIO_PU_DYN_RANGE_COMP     6

    #define USB_AUDIO_CONTROL_EXTENSION_UNIT    8

/*
 * Audio Streaming Interface (SI) descriptor subtypes
 */
#define USB_AUDIO_SI_UNDEFINED           0

typedef __packed struct
{
    USB_DescriptorSubBase;
                #define USB_AUDIO_SI_GENERAL            1
    uint8_t             bTerminalLink;              // UnitID of the output terminal
    uint8_t             bDelay;                     // Interface delay
    uint16_t            wFormatFlag;
                #define USB_AUDIO_SI_FF_PCM             1
} USBAudio_SI_General;

#define USB_AUDIO_SI_FORMAT_TYPE        2

// Equivalent to uint32 USBAudio_sampleFreq(uint8_t*)
#define USBAudio_sampleFreq(charptr) ((charptr)[0] | ((charptr)[1] << 8) | ((charptr)[2] << 16))

typedef __packed struct
{
    USB_DescriptorSubBase;
    uint8_t             bFormatType;
                #define USB_AUDIO_SI_FORMAT_TYPE_I      1
                #define USB_AUDIO_SI_FORMAT_TYPE_III    3
    uint8_t             bNrChannels;
    uint8_t             bSubFrameSize;              // bytes per audio sub frame
    uint8_t             bBitResolution;             // bits per sample
    uint8_t             bSamFreqType;
    uint8_t             tSamFreq[3];                // Sample frequency (Hz)
} USBAudio_SI_FormatType;

typedef __packed struct
{
    USB_DescriptorSubBase;
    uint8_t             bFormatType;
                #define USB_AUDIO_SI_FORMAT_TYPE_II     2
    uint16_t            wMaxBitRate;
    uint16_t            wSamplesPerFrame;
    uint8_t             bSamFreqType;
    uint8_t             tSamFreq[3];                // Sample frequency (Hz)
} USBAudio_SI_FormatType_II;


#define USB_AUDIO_SI_FORMAT_SPECIFIC    3


/*
 * Audio Streaming Endpoint (SE) descriptor subtypes
 */
#define USB_AUDIO_EP_UNDEFINED          0

typedef __packed struct
{
    USB_DescriptorSubBase;
                #define USB_AUDIO_SE_GENERAL            1
    uint8_t             bmAttributes;
                #define USB_AUDIO_SE_CTRL_SAMP_FREQ     (1 << 0)
                #define USB_AUDIO_SE_CTRL_PITCH         (1 << 1)
                #define USB_AUDIO_SE_MAXPACKETS_ONLY    (1 << 7)
    uint8_t             bLockDelayUnits;
    uint16_t            wLockDelay;
} USBAudio_SE_General;

#endif
