
/**
 ******************************************************************************
 *
 * @file        MG32_USBD_Audio_Core.h
 * @brief       The code is USB audio C file.
 *
 * @par         Project
 *              MG32
 * @version     V1.02
 * @date        2022/09/26
 * @author      Megawin Software Center
 * @copyright   Copyright (c) 2017 MegaWin Technology Co., Ltd.
 *              All rights reserved.
 * 
 ******************************************************************************* 
 * @par Disclaimer
 * The Demo software is provided "AS IS" without any warranty, either
 * expressed or implied, including, but not limited to, the implied warranties
 * of merchantability and fitness for a particular purpose. The author will
 * not be liable for any special, incidental, consequential or indirect
 * damages due to loss of data or any other reason.
 * These statements agree with the world wide and local dictated laws about
 * authorship and violence against these laws.
 *******************************************************************************
 *******************************************************************************
 */
 

/* Includes ------------------------------------------------------------------*/
#include "MG32_USBD_Audio_Core.h"
#include "MG32_USB_DRV.h"
#include "MG32_USBD_Core.h"
#include "MG32_GPIO_DRV.h"

/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
USBAudio_TypeDef  USB_Audio;
 
__ALIGNED(2) uint8_t  TST_USB_AudioBuf[64];

/* Private function prototypes -----------------------------------------------*/
uint8_t USB_Audio_GetEndpointDataSize( uint32_t Audio_SamFreq , uint8_t Audio_BITRES , uint8_t Audio_ch);

/* Exported variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/* External vairables --------------------------------------------------------*/

/**
 *******************************************************************************
 * @brief	    
 * @details     
 * @return      
 * @exception   
 * @note       " Now no not support  22.05 & 44.1 KHz "              
 *******************************************************************************
 */
uint8_t USB_Audio_GetEndpointDataSize( uint32_t Audio_SamFreq , uint8_t Audio_BITRES , uint8_t Audio_ch)
{
    uint8_t Tmp;
    
    Tmp = (uint8_t)(AUDIO_EP_SIZE (Audio_SamFreq , Audio_BITRES , Audio_ch));
    
    return(Tmp);
    
    
//    return( ( AUDIO_EP_SIZE (Audio_SamFreq , Audio_BITRES , Audio_ch)));
    
}

/**
 *******************************************************************************
 * @brief	    
 * @details     
 * @return      
 * @exception   
 * @note      
 * @par         
 *******************************************************************************
 */
void USB_Audio_Inital(void)
{
    //=====================================================================
    //Audio  Mute & Volume relationship parameter inital.
    //-----------------------------------------------------------------------
    USB_Audio.AudioIN_MUTE  = 0;
    USB_Audio.AudioOUT_MUTE = 0;
    USB_Audio.IdleRate      = 0;
    
    //-----------------------------------------------------------------------
    USB_Audio.AudioIN_Volume[0][AUDIO_DATA_CUR]     = 0xF700;                                 // -8.985 dB
    USB_Audio.AudioIN_Volume[1][AUDIO_DATA_CUR]     = 0xF700;                                 // -8.985 dB
    
    USB_Audio.AudioOUT_Volume[0][AUDIO_DATA_CUR]    = 0xF700;                                 // -8.985 dB
    USB_Audio.AudioOUT_Volume[1][AUDIO_DATA_CUR]    = 0xF700;                                 // -8.985 dB
    //-----------------------------------------------------------------------
    USB_Audio.AudioIN_Volume[0][AUDIO_DATA_MIN]     = 0xD800;                                 // -39.936 dB
    USB_Audio.AudioIN_Volume[1][AUDIO_DATA_MIN]     = 0xD800;                                 // -39.936 dB
    
    USB_Audio.AudioOUT_Volume[0][AUDIO_DATA_MIN]    = 0xD800;                                 // -39.936 dB
    USB_Audio.AudioOUT_Volume[1][AUDIO_DATA_MIN]    = 0xD800;                                 // -39.936 dB
    //-----------------------------------------------------------------------
    USB_Audio.AudioIN_Volume[0][AUDIO_DATA_MAX]     = 0x1500;                                 // 20.966 dB
    USB_Audio.AudioIN_Volume[1][AUDIO_DATA_MAX]     = 0x1500;                                 // 20.966 dB
    
    USB_Audio.AudioOUT_Volume[0][AUDIO_DATA_MAX]    = 0x1500;                                 // 20.966 dB
    USB_Audio.AudioOUT_Volume[1][AUDIO_DATA_MAX]    = 0x1500;                                 // 20.966 dB
    //-----------------------------------------------------------------------
    USB_Audio.AudioIN_Volume[0][AUDIO_DATA_RES]     = 0x0010;                                 // 0.0624 dB
    USB_Audio.AudioIN_Volume[1][AUDIO_DATA_RES]     = 0x0010;                                 // 0.0624 dB
    
    USB_Audio.AudioOUT_Volume[0][AUDIO_DATA_RES]    = 0x0010;                                 // 0.0624 dB
    USB_Audio.AudioOUT_Volume[1][AUDIO_DATA_RES]    = 0x0010;                                 // 0.0624 dB
    //-----------------------------------------------------------------------
    USB_Audio.AudioOUT_SampleFreq[AUDIO_DATA_CUR]   = OUT_tCURSamFreq;
    USB_Audio.AudioOUT_SampleFreq[AUDIO_DATA_MIN]   = OUT_tLowSamFreq;
    USB_Audio.AudioOUT_SampleFreq[AUDIO_DATA_MAX]   = OUT_tUpperSamFreq;
    USB_Audio.AudioOUT_SampleFreq[AUDIO_DATA_RES]   = 0;
    
    USB_Audio.AudioIN_SampleFreq[AUDIO_DATA_CUR]    = IN_tCURSamFreq;
    USB_Audio.AudioIN_SampleFreq[AUDIO_DATA_MIN]    = IN_tLowSamFreq;
    USB_Audio.AudioIN_SampleFreq[AUDIO_DATA_MAX]    = IN_tUpperSamFreq;
    USB_Audio.AudioIN_SampleFreq[AUDIO_DATA_RES]    = 0;
                                       

    USB_Audio.AudioOUT_PitchEnable_CUR = 0;
    USB_Audio.AudioIN_PitchEnable_CUR  = 0;
    
    USB_Audio.AudioOUT_DataByte = USB_Audio_GetEndpointDataSize(USB_Audio.AudioOUT_SampleFreq[AUDIO_DATA_CUR],OUT_BitResolution,OUT_Channel);
    USB_Audio.AudioIN_DataByte  = USB_Audio_GetEndpointDataSize(USB_Audio.AudioIN_SampleFreq[AUDIO_DATA_CUR],IN_BitResolution,IN_Channel);
    
    //=======================================================================
    //Audio Control Parameter inital
    USB_Audio.AudioOUT_Busyflag         = 0;
    USB_Audio.AudioOUT_Cnt              = 0;
                                       
    USB_Audio.AudioIN_Busyflag          = 0;
    USB_Audio.AudioIN_Cnt               = 0;
    
    USB_Audio.AudioMultimedia_Busyflag  = 0;
    USB_Audio.AudioOUT_MultimediaStatus = AUDIO_MULTIMEDIA_IDLE;
    USB_Audio.AudioIN_MultimediaStatus  = AUDIO_MULTIMEDIA_IDLE;
    
    //======================================================================
    USB_Audio_InitCallback();
    

}
/**
 *******************************************************************************
 * @brief	    
 * @details     
 * @return      
 * @exception   
 * @note      
 * @par         
 *******************************************************************************
 */ 
void USB_Audio_Control_Request(uint8_t USBA_RequestType)
{
    ctype USBA_CTR_ReqTmp;
    
    Ep0.DataStage      = STATUSSTAGE;
    USB_Audio.bRequest = Ep0.RxTx[1];
    USB_Audio.CN       = (Ep0.RxTx[2] - 1);
    USB_Audio.CS       = Ep0.RxTx[3];
    USB_Audio.IDS      = Ep0.RxTx[5];
    Ep0.All            = (((uint32_t)(Ep0.RxTx[7] << 8 ))+ Ep0.RxTx[6]);
    
    if( USBA_RequestType == GET_REQUEST)
    {
        Ep0.Buf = &Ep0.RxTx[0];
        
        switch( USB_Audio.CS)
        {
            case FU_CONTROL_MUTE:
                                   switch(USB_Audio.bRequest)
                                   {
                                       case USB_AUDIO_REQUEST_GET_CUR:
                                                                      if( USB_Audio.IDS == AUDIO_OUT_FEATURE_ID)
                                                                      {
                                                                          Ep0.DataStage      = DATASTAGE; 
                                                                          Ep0.RxTx[0] = USB_Audio.AudioOUT_MUTE;
                                                                      }
                                                                      else if(USB_Audio.IDS == AUDIO_IN_FEATURE_ID)
                                                                      {
                                                                          Ep0.DataStage      = DATASTAGE; 
                                                                          Ep0.RxTx[0]        = USB_Audio.AudioIN_MUTE;
                                                                      }
                                                                      
                                                                      break;
                                       default:
                                                                      break;
                                   }
                                   break;
            case FU_CONTROL_VOLUME:
                                   switch(USB_Audio.bRequest)
                                   {
                                       case USB_AUDIO_REQUEST_GET_CUR:
                                       case USB_AUDIO_REQUEST_GET_MIN:
                                       case USB_AUDIO_REQUEST_GET_MAX:
                                       case USB_AUDIO_REQUEST_GET_RES:
                                                                      USBA_CTR_ReqTmp.W = 0;
                                       
                                                                      if( USB_Audio.IDS == AUDIO_OUT_FEATURE_ID)
                                                                      {
                                                                          Ep0.DataStage      = DATASTAGE; 
                                                                          
                                                                          USBA_CTR_ReqTmp.W  = USB_Audio.AudioOUT_Volume[USB_Audio.CN][( (USB_Audio.bRequest & 0x0F)-1)];
                                                                      }
                                                                      else if(USB_Audio.IDS == AUDIO_IN_FEATURE_ID)
                                                                      {
                                                                          Ep0.DataStage      = DATASTAGE; 
                                                                          
                                                                          USBA_CTR_ReqTmp.W  = USB_Audio.AudioIN_Volume[USB_Audio.CN][(( USB_Audio.bRequest & 0x0F)-1)];
                                                                      }
                                                                      
                                                                      Ep0.RxTx[0] = USBA_CTR_ReqTmp.B[0];
                                                                      Ep0.RxTx[1] = USBA_CTR_ReqTmp.B[1];
                                                                      Ep0.RxTx[2] = USBA_CTR_ReqTmp.B[2];
                                                                      Ep0.RxTx[3] = USBA_CTR_ReqTmp.B[3];
                                                                      break;
                                       default:
                                                                      break;
                                   }
                                   break;
            default:
                                   break;            
        }
        API_USBD_ControlRead();
    }
    else
    {
        switch( USB_Audio.CS)
        {
            case FU_CONTROL_MUTE:        
                                   switch(USB_Audio.bRequest)
                                   {
                                       case USB_AUDIO_REQUEST_GET_CUR:
                                                                      Ep0.DataStage      = AUDIO_CONTROL; 
                                                                      break;
                                       default:
                                                                      break;
                                   }
                                   break;
            case FU_CONTROL_VOLUME:
                                   switch(USB_Audio.bRequest)
                                   {
                                       case USB_AUDIO_REQUEST_SET_CUR:
                                       case USB_AUDIO_REQUEST_SET_MIN:
                                       case USB_AUDIO_REQUEST_SET_MAX:
                                       case USB_AUDIO_REQUEST_SET_RES:    
                                                                      Ep0.DataStage      = AUDIO_CONTROL; 
                                                                      break;
                                       default:
                                                                      break;
                                   }
                                   
                                   break;
            default:
                                   break;
            
        }
        
        if(Ep0.DataStage  == AUDIO_CONTROL)
        {
            USB_SetEndpointStatus(USB_EP0, EP_RX_VALID);
        }
        else
        {
            USB_SetEndpointStatus(USB_EP0, EP_RX_STALL_TX_STALL);
        }
    }
}

/**
 *******************************************************************************
 * @brief	    
 * @details     
 * @return      
 * @exception   
 * @note      
 * @par         
 *******************************************************************************
 */ 
void USB_Audio_Endpoint_Request(void)
{
    ctype  USB_AudioEPReq_Tmp;
    
    Ep0.DataStage      = STATUSSTAGE;
    USB_Audio.bRequest = Ep0.RxTx[1];
    USB_Audio.CS       = Ep0.RxTx[3];
    USB_Audio.IDS      = Ep0.RxTx[4];
    Ep0.All            = (((uint32_t)(Ep0.RxTx[7] << 8 ))+ Ep0.RxTx[6]);

    if( Ep0.RxTx[0] & GET_REQUEST)
    {
        Ep0.Buf = &Ep0.RxTx[0];
        
        switch( USB_Audio.CS)
        {
            case SAMPLING_FREQ_CONTROL:
                                       switch(USB_Audio.bRequest)
                                       {
                                           case USB_AUDIO_REQUEST_GET_CUR:                     
                                           case USB_AUDIO_REQUEST_GET_MIN:
                                           case USB_AUDIO_REQUEST_GET_MAX: 
                                           case USB_AUDIO_REQUEST_GET_RES:
                                                                          USB_AudioEPReq_Tmp.W = 0;
                                                                          if(USB_Audio.IDS == (USB_EP_IN |IN_ENDPOINT_ID))
                                                                          {
                                                                              Ep0.DataStage      = DATASTAGE; 
                                                                              USB_AudioEPReq_Tmp.W = USB_Audio.AudioIN_SampleFreq[ ( (USB_Audio.bRequest & 0x0F)-1)];
                                                                          }
                                                                          else if(USB_Audio.IDS == ( USB_EP_OUT | OUT_ENDPOINT_ID))
                                                                          {
                                                                              Ep0.DataStage      = DATASTAGE; 
                                                                              USB_AudioEPReq_Tmp.W = USB_Audio.AudioOUT_SampleFreq[( (USB_Audio.bRequest & 0x0F)-1)];
                                                                          }
                                                                          Ep0.RxTx[0] = USB_AudioEPReq_Tmp.B[0];
                                                                          Ep0.RxTx[1] = USB_AudioEPReq_Tmp.B[1];
                                                                          Ep0.RxTx[2] = USB_AudioEPReq_Tmp.B[2];
                                                                          break;
                                           default:
                                                                          break;
                                       }
                                       break;
            case PITCH_CONTROL:
                                       switch(USB_Audio.bRequest)
                                       {
                                           case USB_AUDIO_REQUEST_GET_CUR:
                                                                          if(USB_Audio.IDS ==IN_ENDPOINT_ID)
                                                                          {
                                                                              Ep0.DataStage      = DATASTAGE; 
                                                                              Ep0.RxTx[0]        = USB_Audio.AudioIN_PitchEnable_CUR;
                                                                          }
                                                                          else if(USB_Audio.IDS ==OUT_ENDPOINT_ID)
                                                                          {
                                                                              Ep0.DataStage      = DATASTAGE; 
                                                                              Ep0.RxTx[0]        = USB_Audio.AudioOUT_PitchEnable_CUR;
                                                                          }
                                                                          break;
                                           default:        
                                                                          break;
                                       }
                                       break;
            default:
                                       break;
        }
        API_USBD_ControlRead();
    }
    else
    {
        switch( USB_Audio.CS)
        {
            case SAMPLING_FREQ_CONTROL:
                                       switch(USB_Audio.bRequest)
                                       {
                                           case USB_AUDIO_REQUEST_SET_CUR:                     
                                           case USB_AUDIO_REQUEST_SET_MIN:
                                           case USB_AUDIO_REQUEST_SET_MAX:
                                           case USB_AUDIO_REQUEST_SET_RES:
                                                                          USB_AudioEPReq_Tmp.W = 0;
                                                                          if( USB_Audio.IDS == ( USB_EP_IN | IN_ENDPOINT_ID))
                                                                          {
                                                                              Ep0.DataStage      = AUDIO_ENDPOINT; 
                                                                          }
                                                                          else if( USB_Audio.IDS == ( USB_EP_OUT | OUT_ENDPOINT_ID))
                                                                          {
                                                                              Ep0.DataStage      = AUDIO_ENDPOINT; 
                                                                          }
                                                                          break;
                                           default:
                                                                          break;
                                       }
                                       break;
            case PITCH_CONTROL:
                                       switch(USB_Audio.bRequest)
                                       {
                                           case USB_AUDIO_REQUEST_GET_CUR:
                                                                          if( USB_Audio.IDS == ( USB_EP_IN | IN_ENDPOINT_ID))
                                                                          {
                                                                              Ep0.DataStage      = AUDIO_ENDPOINT; 
                                                                          }
                                                                          else if( USB_Audio.IDS == ( USB_EP_OUT | OUT_ENDPOINT_ID))
                                                                          {
                                                                              Ep0.DataStage      = AUDIO_ENDPOINT; 
                                                                          }
                                                                          break;
                                           default:        
                                                                          break;
                                       }
                                       break;
            default:
                                       break;
        }
        
        if(Ep0.DataStage  == STATUSSTAGE)
        {
            USB_SetEndpointStatus(USB_EP0, EP_RX_STALL_TX_STALL);
        }

    }
    
}
/**
 *******************************************************************************
 * @brief	    
 * @details     
 * @return      
 * @exception   
 * @note      
 * @par         
 *******************************************************************************
 */
void USB_Audio_Control_SetRequest(void)
{
    uint8_t USBA_cBLen;
    
    USBA_cBLen = (uint8_t)USB_GetEndpointRXSize(USB_EP0);
    
    USB_ReadEndpointData( USB_EP0, Ep0.RxTx , 0 , USBA_cBLen);
    
    
    switch( USB_Audio.CS )
    {
        case FU_CONTROL_MUTE :
                                if( USB_Audio.IDS == AUDIO_OUT_FEATURE_ID)
                                {    
                                    USB_Audio.AudioOUT_MUTE = Ep0.RxTx[0];
 
                                    USB_AudioOUT_UpdateMuteCallback();
                                }
                                else if( USB_Audio.IDS == AUDIO_IN_FEATURE_ID)
                                {
                                    USB_Audio.AudioIN_MUTE = Ep0.RxTx[0];
                                    
                                    USB_AudioIN_UpdateMuteCallback();
                                }
                                
                                break;
        case FU_CONTROL_VOLUME:
                                if( USB_Audio.IDS == AUDIO_OUT_FEATURE_ID)
                                {  
                                    switch(USB_Audio.bRequest)
                                    {
                                        case USB_AUDIO_REQUEST_SET_CUR:
                                                                       USB_Audio.AudioOUT_Volume[USB_Audio.CN][AUDIO_DATA_CUR] =  (((uint16_t)( Ep0.RxTx[1] << 8 )) + Ep0.RxTx[0]);
                                                                       USB_AudioOUT_UpdateVolumeStatusCallback();
                                                                       break;
                                        case USB_AUDIO_REQUEST_SET_MIN:
                                                                       USB_Audio.AudioOUT_Volume[USB_Audio.CN][AUDIO_DATA_MIN] =  (((uint16_t)( Ep0.RxTx[1] << 8 )) + Ep0.RxTx[0]);
                                                                       break;
                                        case USB_AUDIO_REQUEST_SET_MAX:
                                                                       USB_Audio.AudioOUT_Volume[USB_Audio.CN][AUDIO_DATA_MAX] =  (((uint16_t)( Ep0.RxTx[1] << 8 )) + Ep0.RxTx[0]);
                                                                       break;
                                        case USB_AUDIO_REQUEST_SET_RES:
                                                                       USB_Audio.AudioOUT_Volume[USB_Audio.CN][AUDIO_DATA_RES] =  (((uint16_t)( Ep0.RxTx[1] << 8 )) + Ep0.RxTx[0]);
                                                                       break;
                                        default:
                                                                       break;
                                    }
                                }
                                else if( USB_Audio.IDS == AUDIO_IN_FEATURE_ID)            
                                {
                                    switch(USB_Audio.bRequest)
                                    {
                                        case USB_AUDIO_REQUEST_SET_CUR:
                                                                       USB_Audio.AudioIN_Volume[USB_Audio.CN][AUDIO_DATA_CUR] =  (((uint16_t)( Ep0.RxTx[1] << 8 )) + Ep0.RxTx[0]);
                                                                       USB_AudioIN_UpdateVolumeStatusCallback();
                                                                       break;
                                        case USB_AUDIO_REQUEST_SET_MIN:
                                                                       USB_Audio.AudioIN_Volume[USB_Audio.CN][AUDIO_DATA_MIN] =  (((uint16_t)( Ep0.RxTx[1] << 8 )) + Ep0.RxTx[0]);
                                                                       break;
                                        case USB_AUDIO_REQUEST_SET_MAX:
                                                                       USB_Audio.AudioIN_Volume[USB_Audio.CN][AUDIO_DATA_MAX] =  (((uint16_t)(Ep0.RxTx[1] << 8 )) + Ep0.RxTx[0]);
                                                                       break;
                                        case USB_AUDIO_REQUEST_SET_RES:
                                                                       USB_Audio.AudioIN_Volume[USB_Audio.CN][AUDIO_DATA_RES] =  (((uint16_t)(Ep0.RxTx[1] << 8 )) + Ep0.RxTx[0]);
                                                                       break;
                                        default:
                                                                       break;
                                    }
                                }
                                break;                                
        default:
                                break;
    }

    
    Ep0.All = Ep0.All - USBA_cBLen;
    
    if( Ep0.All == 0)
    {
        Ep0.DataStage = STATUSSTAGE;
        USB_SetEndpointTXSize(USB_EP0, 0);
        USB_SetEndpointStatus(USB_EP0, EP_TX_VALID);
    }
    else
    {
        USB_SetEndpointStatus(USB_EP0, EP_RX_VALID);
    }
}

/**
 *******************************************************************************
 * @brief	    
 * @details     
 * @return      
 * @exception   
 * @note      
 * @par         
 *******************************************************************************
 */
void USB_Audio_Endpoint_SetRequest(void)
{
    ctype   USBA_sEPREQ_Tmp;
    uint8_t USBA_eBLen;
    
    USBA_eBLen = (uint8_t)USB_GetEndpointRXSize(USB_EP0);
    
    USB_ReadEndpointData( USB_EP0, Ep0.RxTx , 0 , USBA_eBLen);
    
    switch( USB_Audio.CS )
    {
        case SAMPLING_FREQ_CONTROL:
                                   USBA_sEPREQ_Tmp.W    = 0;
                                   USBA_sEPREQ_Tmp.B[0] = Ep0.RxTx[0];
                                   USBA_sEPREQ_Tmp.B[1] = Ep0.RxTx[1];
                                   USBA_sEPREQ_Tmp.B[2] = Ep0.RxTx[2];
                                   if( USB_Audio.IDS == ( USB_EP_OUT | OUT_ENDPOINT_ID))
                                   {  
                                       switch(USB_Audio.bRequest)
                                       {
                                           case USB_AUDIO_REQUEST_SET_CUR:
                                                                          // To do...
                                                                          USB_Audio.AudioOUT_SampleFreq[AUDIO_DATA_CUR] = USBA_sEPREQ_Tmp.W;
                                                                          USB_Audio.AudioOUT_DataByte = USB_Audio_GetEndpointDataSize(USB_Audio.AudioOUT_SampleFreq[AUDIO_DATA_CUR],OUT_BitResolution,OUT_Channel);
                                                                                                         
                                                                          USB_AudioOUT_UpdateSampleFrequenceCallback();
                                                                          break;
                                           case USB_AUDIO_REQUEST_SET_MIN:
                                                                          // To do...
                                                                          USB_Audio.AudioOUT_SampleFreq[AUDIO_DATA_MIN] = USBA_sEPREQ_Tmp.W;
                                                                          break;
                                           case USB_AUDIO_REQUEST_SET_MAX:
                                                                          // To do...
                                                                          USB_Audio.AudioOUT_SampleFreq[AUDIO_DATA_MAX] = USBA_sEPREQ_Tmp.W;
                                                                          break;
                                           case USB_AUDIO_REQUEST_SET_RES:
                                                                          // To do...
                                                                          USB_Audio.AudioOUT_SampleFreq[AUDIO_DATA_RES] = USBA_sEPREQ_Tmp.W;
                                                                          break;
                                           default:
                                                                          break;
                                       }
                                   }
                                   else if( USB_Audio.IDS == ( USB_EP_IN | IN_ENDPOINT_ID))
                                   {
                                       switch(USB_Audio.bRequest)
                                       {
                                           case USB_AUDIO_REQUEST_SET_CUR:
                                                                          // To do...
                                                                          USB_Audio.AudioIN_SampleFreq[AUDIO_DATA_CUR] = USBA_sEPREQ_Tmp.W;
                                                                          USB_Audio.AudioIN_DataByte = USB_Audio_GetEndpointDataSize(USB_Audio.AudioIN_SampleFreq[AUDIO_DATA_CUR],IN_BitResolution,IN_Channel);
                                                                          
                                                                          USB_AudioIN_UpdateSampleFrequenceCallback();
                                                                          break;
                                           case USB_AUDIO_REQUEST_SET_MIN:
                                                                          // To do...
                                                                          USB_Audio.AudioIN_SampleFreq[AUDIO_DATA_MIN] = USBA_sEPREQ_Tmp.W;
                                                                          break;
                                           case USB_AUDIO_REQUEST_SET_MAX:
                                                                          // To do...
                                                                          USB_Audio.AudioIN_SampleFreq[AUDIO_DATA_MAX] = USBA_sEPREQ_Tmp.W;
                                                                          break;
                                           case USB_AUDIO_REQUEST_SET_RES:
                                                                          // To do...
                                                                          USB_Audio.AudioIN_SampleFreq[AUDIO_DATA_RES] = USBA_sEPREQ_Tmp.W;
                                                                          break;
                                           default:
                                                                          break;
                                       }
                                   }
                                   break;
        case PITCH_CONTROL:
                                   if( USB_Audio.IDS == OUT_ENDPOINT_ID)
                                   {    
                                       USB_Audio.AudioOUT_MUTE = Ep0.RxTx[0];
                                   }
                                   else if( USB_Audio.IDS == IN_ENDPOINT_ID)
                                   {
                                       USB_Audio.AudioIN_MUTE = Ep0.RxTx[0];
                                   }
                                   break;
        default:
                                   break;
    }
    
    
    
    Ep0.All = Ep0.All - USBA_eBLen;
    
    if( Ep0.All == 0)
    {
        Ep0.DataStage = STATUSSTAGE;
        USB_SetEndpointTXSize(USB_EP0, 0);
        USB_SetEndpointStatus(USB_EP0, EP_TX_VALID);
    }
    else
    {
        USB_SetEndpointStatus(USB_EP0, EP_RX_VALID);
    }
}

/**
 *******************************************************************************
 * @brief	    
 * @details     
 * @return      
 * @exception   
 * @note      
 * @par         
 *******************************************************************************
 */
void USB_Audio_OUTData(void)
{
    if( USB_Audio.AudioOUT_Busyflag == 0)
    {
        USB_Audio.AudioOUT_Busyflag  = 1;
        
        USB_Audio.AudioOUT_Cnt = (uint8_t)USB_GetEndpointRXSize(OUT_ENDPOINT_REG);
        
        USB_ReadEndpointData( OUT_ENDPOINT_REG , USB_Audio.AudioOUT_Buf , 0 , USB_Audio.AudioOUT_Cnt);
        
        USB_Audio_OUTDataCallback(USB_Audio.AudioOUT_Cnt);
    }

    USB_SetEndpointStatus( OUT_ENDPOINT_REG, EP_RX_VALID); 
}
/**
 *******************************************************************************
 * @brief	    
 * @details     
 * @return      
 * @exception   
 * @note      
 * @par         
 *******************************************************************************
 */
void USB_Audio_INDataTrigger(void)
{
    if( USB_Audio.AudioIN_Busyflag == 0)
    {
        USB_Audio.AudioIN_Cnt = 0; 
        USB_Audio_INDataTriggerCallback();
        
        if(USB_Audio.AudioIN_Cnt !=0)
        {
            USB_Audio.AudioIN_Busyflag = 1;
            
            USB_WriteEndpointData( IN_ENDPOINT_REG , USB_Audio.AudioIN_Buf, 0, USB_Audio.AudioIN_Cnt);
         
            USB_SetEndpointTXSize( IN_ENDPOINT_REG , USB_Audio.AudioIN_Cnt);

            USB_SetEndpointStatus( IN_ENDPOINT_REG, EP_TX_VALID);             
        }
    }
}
/**
 *******************************************************************************
 * @brief	    
 * @details     
 * @return      
 * @exception   
 * @note      
 * @par         
 *******************************************************************************
 */
void USB_Audio_INDataContinuous(void)
{
    USB_Audio.AudioIN_Cnt = 0;
    USB_Audio_INDataContinuousCallback();
    
    if( USB_Audio.AudioIN_Cnt  != 0 )
    {   
        USB_Audio.AudioIN_Busyflag = 1;
        
        USB_WriteEndpointData( IN_ENDPOINT_REG , USB_Audio.AudioIN_Buf, 0, USB_Audio.AudioIN_Cnt);
        
        USB_SetEndpointTXSize( IN_ENDPOINT_REG , USB_Audio.AudioIN_Cnt);
        
        USB_SetEndpointStatus( IN_ENDPOINT_REG, EP_TX_VALID);         
    }
    else
    {
       USB_Audio.AudioIN_Busyflag = 0;
    }
}
/**
 *******************************************************************************
 * @brief	    
 * @details     
 * @return      
 * @exception   
 * @note      
 * @par         
 *******************************************************************************
 */
void USB_Audio_TriggerMultimediaControl( MultimediaFunction_TypeDef mFunction, MultimediaStatus_TypeDef MStatus)
{
//    ctype USBAudioMultiTmp;
    
    if( USB_Audio.AudioMultimedia_Busyflag == 0)
    {
        if( (mFunction & AUDIO_MULTIMEDIA_AUDIO_TYPE_MASK) == AUDIO_MULTIMEDIA_AUDIO_IN)
        {
            USB_Audio.AudioMultimedia_Buf[0] = USB_MULTIMEDIA_AUDIOIN_ID;
            
            if( MStatus == AUDIO_MULTIMEDIA_BREAK)
            {
                USB_Audio.AudioIN_MultimediaStatus = USB_Audio.AudioIN_MultimediaStatus & (uint8_t)(~mFunction);
            }
            else
            {
                USB_Audio.AudioIN_MultimediaStatus = USB_Audio.AudioIN_MultimediaStatus | (uint8_t)(mFunction);
            }
            
            USB_Audio.AudioMultimedia_Buf[1] = USB_Audio.AudioIN_MultimediaStatus;
        }
        else
        {
            USB_Audio.AudioMultimedia_Buf[0] = USB_MULTIMEDIA_AUDIOOUT_ID;
            
            if( MStatus == AUDIO_MULTIMEDIA_BREAK)
            {
                USB_Audio.AudioOUT_MultimediaStatus = USB_Audio.AudioOUT_MultimediaStatus & (uint8_t)(~mFunction);
            }
            else
            {
                USB_Audio.AudioOUT_MultimediaStatus = USB_Audio.AudioOUT_MultimediaStatus | (uint8_t)(mFunction);
            }
            
            
            USB_Audio.AudioMultimedia_Buf[1] = USB_Audio.AudioOUT_MultimediaStatus;
        }
        
        
        USB_WriteEndpointData( USB_MULTIMEDIA_ENDPOINT_REG , &USB_Audio.AudioMultimedia_Buf[0], 0, ( USB_MULTIMEDIA_DATABYTE + 1));
        
        USB_SetEndpointTXSize( USB_MULTIMEDIA_ENDPOINT_REG , ( USB_MULTIMEDIA_DATABYTE + 1));
        
        USB_SetEndpointStatus( USB_MULTIMEDIA_ENDPOINT_REG, EP_TX_VALID); 
        
        USB_Audio.AudioMultimedia_Busyflag = 1;
    }
}


/**
 * @name  User callback function.
 *   		
 */ 

///@{
 /**
 *******************************************************************************
 * @brief	    
 * @details     
 * @return      
 * @exception   
 * @note      
 * @par         
 *******************************************************************************
 */
__weak void USB_Audio_InitCallback(void)
{
    //================================================
    //To inital User relationship control.
    //    * Intial Audio OUT buffer ( USB_Audio.AudioOUT_Buf )
    //    * Inital Audio IN buffer (USB_Audio.AudioIN_Buf)
    
    
    USB_Audio.AudioOUT_Buf = &TST_USB_AudioBuf[0];
    
}    
 /**
 *******************************************************************************
 * @brief	    
 * @details     
 * @return      
 * @exception   
 * @note      
 * @par         
 *******************************************************************************
 */
__weak void USB_Audio_OUTDataCallback( uint8_t AudioData_Byte)
{
    //================================================
    //If wanting to receiving next Audio OUT data from USB :
    //    *. Setting next buffer pointer.]
    ((void)(AudioData_Byte));
}

 /**
 *******************************************************************************
 * @brief	    
 * @details     
 * @return      
 * @exception   
 * @note      
 * @par         
 *******************************************************************************
 */
__weak void USB_Audio_INDataContinuousCallback(void)
{
    //================================================
    //if Audio IN still have data :
    //    * Set USB_Audio.AudioIN_Cnt.
    //    * Set Next data buffer pointer.
}

 /**
 *******************************************************************************
 * @brief	    
 * @details     
 * @return      
 * @exception   
 * @note      
 * @par         
 *******************************************************************************
 */
__weak void USB_Audio_INDataTriggerCallback(void)
{
    //================================================
    //If Audio IN want to send data to USB.
    //    * Set USB_Audio.AudioIN_Cnt.
    //    * Set Next data buffer pointer.
}

 /**
 *******************************************************************************
 * @brief	   Host called Audio OUT MUTE status now. 
 * @details     
 * @return      
 * @exception   
 * @note       
 * @par         
 *******************************************************************************
 */
__weak void USB_AudioOUT_UpdateMuteCallback(void)
{
    //=================================================
    //To Read USB_Audio.AudioOUT_MUTE value 
    //    * USB_Audio.AudioOUT_MUTE = 1  : Mute.
    //                              = 0  : No Mute.
    
}
 /**
 *******************************************************************************
 * @brief	    Host called Audio IN MUTE status now.
 * @details     
 * @return      
 * @exception   
 * @note      
 * @par         
 *******************************************************************************
 */
__weak void USB_AudioIN_UpdateMuteCallback(void)
{
    //=================================================
    //To Read USB_Audio.AudioIN_MUTE value 
    //    * USB_Audio.AudioIN_MUTE = 1  : Mute.
    //                             = 0  : No Mute.    
    
}
 /**
 *******************************************************************************
 * @brief	    Host called Audio IN MUTE status now.
 * @details     
 * @return      
 * @exception   
 * @note      
 * @par         
 *******************************************************************************
 */
__weak void USB_AudioOUT_UpdateVolumeStatusCallback(void)
{
    //=================================================
    //To Read USB_Audio.AudioOUT_Volume value :
    //    1. The date is 16 bit and signed  date but the code save to unsigned date.
    //    2. The data :
    //         0x0002 =  0.0078 db
    //         0x0001 =  0.0039 dB
    //         0x0000 =  0.0000 dB
    //         0xFFFF = -0.0039 dB
    //    3. USB_Audio.AudioOUT_Volume[0][AUDIO_DATA_CUR] = Audio OUT L Front channel current volume value.
    //    4. USB_Audio.AudioOUT_Volume[1][AUDIO_DATA_CUR] = Audio OUT R Front channel current volume value.
}

 /**
 *******************************************************************************
 * @brief	    Host called Audio IN MUTE status now.
 * @details     
 * @return      
 * @exception   
 * @note      
 * @par         
 *******************************************************************************
 */
__weak void USB_AudioIN_UpdateVolumeStatusCallback(void)
{
    //=================================================
    //To Read USB_Audio.AudioIN_Volume value :
    //    1. The date is 16 bit and signed  date but the code save to unsigned date.
    //    2. The data :
    //         0x0002 =  0.0078 db
    //         0x0001 =  0.0039 dB
    //         0x0000 =  0.0000 dB
    //         0xFFFF = -0.0039 dB
    //    3. USB_Audio.AudioIN_Volume[0][AUDIO_DATA_CUR] = Audio OUT L Front channel current volume value.
    //    4. USB_Audio.AudioIN_Volume[1][AUDIO_DATA_CUR] = Audio OUT R Front channel current volume value.
    
}

 /**
 *******************************************************************************
 * @brief	    Host update Audio OUT sampling frequence now.
 * @details     
 * @return      
 * @exception   
 * @note      
 * @par         
 *******************************************************************************
 */
__weak void USB_AudioOUT_UpdateSampleFrequenceCallback(void)
{
    //================================================
    //Read the following parameter to know Audio OUT sampling frequence relationship information now..
    //    1. USB_Audio.AudioOUT_SampleFreq[AUDIO_DATA_CUR]:  Now Audio OUT sample frequence.
    //    2. USB_Audio.AudioOUT_DataByte : Audio OUT Data max size now.

}

 /**
 *******************************************************************************
 * @brief	    Host update Audio IN sampling frequence now.
 * @details     
 * @return      
 * @exception   
 * @note      
 * @par         
 *******************************************************************************
 */
__weak void USB_AudioIN_UpdateSampleFrequenceCallback(void)
{
    //================================================
    //Read the following parameter to know Audio IN sampling frequence relationship information now..
    //    1. USB_Audio.AudioIN_SampleFreq[AUDIO_DATA_CUR]:  Now Audio IN sample frequence.
    //    2. USB_Audio.AudioIN_DataByte : Audio IN Data max size now.
    
}
///@}



















