/******************************************************************************
*
*  System Name : ARM USB Audio Class Library
*  File Name   : usb0_haudio_api.c
*  Contents    : Audio Storage Class Driver
*  Version     : 0.00.01
*  Device      : ARM
*  Tool-Chain  :
*  OS          :
*
*  Note        :
*
*  Copyright (C) 2014 Renesas Electronics Corporation and
*  Renesas Solutions Corp. All rights reserved.
*
*  History     : Feb.12,2014 Ver..00.01
******************************************************************************/


/*******************************************************************************
Includes   <System Includes> , "Project Includes"
*******************************************************************************/
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include "usb_host_user.h"
#include "usb_haudio_rza1.h"


/*******************************************************************************
Typedef definitions
*******************************************************************************/

/*******************************************************************************
Macro definitions
*******************************************************************************/
/* work buff size */
#define        USB_AUD_UNIT_INFO_SIZE              20
#define        USB_AUD_INPUT_TID_SIZE              20
#define        USB_AUD_UNIT_SRC_ID_SIZE            10
#define        USB_AUD_SEARCH_BUFF_SIZE            64
#define        USB_AUD_CANDIDATE_TID_SIZE          10
/* bDescriptorType */
#define        USB_DT_CS_INTERFACE                 (uint8_t)0x24
/* bDescriptorSubType */
#define        USB_DST_INPUT_TERMINAL              (uint8_t)0x02
#define        USB_DST_OUTPUT_TERMINAL             (uint8_t)0x03
#define        USB_DST_MIXER_UNIT                  (uint8_t)0x04
#define        USB_DST_SELECTOR_UNIT               (uint8_t)0x05
#define        USB_DST_FEATURE_UNIT                (uint8_t)0x06
/* wTerminalType */
#define        USB_T_TYPE_USB_STREAM               (uint16_t)0x0101
#define        USB_T_TYPE_SPEAKER                  (uint16_t)0x0301
typedef struct
{
    uint8_t     unit_id;
    uint8_t     source_id_num;
    uint8_t     source_id_table[USB_AUD_UNIT_SRC_ID_SIZE];
} USB_AUD_UNIT_CONFIG_t;


typedef struct
{
    uint8_t     terminal_id;
    uint8_t     source_id;
} USB_AUD_TERMINAL_INFO_t;


/*******************************************************************************
Imported global variables and functions (from other files)
*******************************************************************************/
extern void usb0_make_dmac0_link_table (uint32_t dir, uint8_t *buf_adr, uint32_t size, uint32_t total_size);
extern void usb0_make_dmac1_link_table (uint32_t dir, uint8_t *buf_adr, uint32_t size, uint32_t total_size);
extern int32_t usb0_check_interrupt_index_0_iso(int32_t index);
extern int32_t usb0_check_interrupt_index_1_iso(int32_t index);


/*******************************************************************************
Exported global variables and functions (to be accessed by other files)
*******************************************************************************/
USB_HAUDIO_t   g_usb0_haudio[ USB_HAUDIO_MAX_DEVADDRESS + 1 ];

USB_HCD_REQUEST_ISO_t    g_usb0_AudioIn_ISO;
USB_HCD_REQUEST_ISO_t    g_usb0_AudioOut_ISO;
USB_HCD_REQUEST_ISO_t    g_usb0_AudioIn_Dummy;
USB_HCD_REQUEST_ISO_t    g_usb0_AudioOut_Dummy;


/*******************************************************************************
Private global variables and functions
*******************************************************************************/
static int32_t  usb0_haudio_check(uint16_t devadr, uint8_t *ConfigDesctable, uint16_t set_config_flag );
static int32_t  usb0_haudio_CheckInterface( uint8_t *InterfaceDescTable, uint8_t *sample_num, uint32_t *sample_rate,
                                            uint8_t *BitResolution, uint8_t *SubframeSize);
static int32_t usb0_haudio_CheckInterface_2( uint8_t *InterfaceDescTable, uint8_t *sample_num, uint32_t *sample_rate,
                                            uint8_t *BitResolution, uint8_t *SubframeSize);
static int32_t usb0_haudio_CheckAudioCtrl_Desc( uint8_t *InterfaceDescTable, uint8_t *SrcId, uint8_t *C_SrcId);
static int32_t usb0_hauido_PipeInfo( uint16_t devadr, uint16_t index,
                                     uint8_t *Table, uint16_t TotalLength,
                                     uint8_t sample_num, uint32_t *sample_rate,
                                     uint8_t speaker_terminal_id,
                                     uint8_t BitResolution, uint8_t SubframeSize);
static void     usb0_haudio_SetDevSts(uint16_t devadr, uint16_t speed);
static void     usb0_haudio_SetDevDetachSts(uint16_t devadr);
static int32_t  usb0_haudio_GetDevSts(uint16_t devadr);

static int32_t usb0_haudio_in_wait( uint16_t devadr, uint32_t timeout );
static int32_t usb0_haudio_in_hcd_request_result( USB_HCD_REQUEST_ISO_t *usb_hcd_request_msg );
static int32_t usb0_haudio_out_wait( uint16_t devadr, uint32_t timeout );
static int32_t usb0_haudio_out_hcd_request_result( USB_HCD_REQUEST_ISO_t *usb_hcd_request_msg );
static int32_t usb0_haudio_check_terminal(uint8_t *config_desc ,uint16_t desc_length, uint8_t* terminal_id);

/*******************************************************************************
* Function Name: usb0_api_haudio_registration
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
void usb0_api_haudio_registration( uint16_t device_address, USB_HAUDIO_REGIST_t *regist )
{
    g_usb0_haudio[ device_address ].audio_regist = regist;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_open
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_open(uint16_t devadr, uint16_t *config, uint16_t set_config_flag, uint16_t speed)
{
    int32_t    ret;

    if( usb0_haudio_GetDevSts(devadr) == USB_HAUDIO_DEV_DET )
    {
        usb0_haudio_SetDevSts(devadr, speed);

        ret = usb0_haudio_check( devadr, (uint8_t *)config, set_config_flag );
        if( ret == USB_HAUDIO_SUCCESS )
        {
            if( g_usb0_haudio[ devadr ].StreamIn.PipeNum != USB_HAUDIO_INVALID )
            {
                ret = usb0_userdef_os_create_mbx( USB_HAUDIO_IN );
                if( ret != USB_HAUDIO_SUCCESS )
                {
                    usb0_haudio_SetDevDetachSts(devadr);
                    return USB_HAUDIO_ERROR;
                }
            }
            if( g_usb0_haudio[ devadr ].StreamOut.PipeNum != USB_HAUDIO_INVALID )
            {
                ret = usb0_userdef_os_create_mbx( USB_HAUDIO_OUT );
                if( ret != USB_HAUDIO_SUCCESS )
                {
                    usb0_haudio_SetDevDetachSts(devadr);
                    return USB_HAUDIO_ERROR;
                }
            }
            g_usb0_haudio[ devadr ].StreamIn.pipe_enable  = USB_HAUDIO_NO;
            g_usb0_haudio[ devadr ].StreamOut.pipe_enable = USB_HAUDIO_NO;
       }
       else
       {
           usb0_haudio_SetDevDetachSts(devadr);
       }
     }
    else
    {
        ret = USB_HAUDIO_ERROR;
    }

    return ret;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_close
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_close(uint16_t devadr)
{
    int32_t    ret;

    if( usb0_haudio_GetDevSts(devadr) != USB_HAUDIO_DEV_DET )
    {
        if( g_usb0_haudio[ devadr ].StreamIn.PipeNum != USB_HAUDIO_INVALID )
        {
            ret = usb0_userdef_os_delete_mbx( USB_HAUDIO_IN );
            if( ret != USB_HAUDIO_SUCCESS )
            {
                return USB_HAUDIO_ERROR;
            }
        }
        if( g_usb0_haudio[ devadr ].StreamOut.PipeNum != USB_HAUDIO_INVALID )
        {
            ret = usb0_userdef_os_delete_mbx( USB_HAUDIO_OUT );
            if( ret != USB_HAUDIO_SUCCESS )
            {
                return USB_HAUDIO_ERROR;
            }
        }

        if( g_usb0_haudio[ devadr ].StreamIn.pipe_enable == USB_HAUDIO_YES )
        {
            usb0_api_haudio_stream_in_stop_link( devadr );
        }
        else if( g_usb0_haudio[ devadr ].StreamIn.pipe_enable == USB_HAUDIO_YES2 )
        {
            usb0_api_haudio_stream_in_stop( devadr );
        }

        if( g_usb0_haudio[ devadr ].StreamOut.pipe_enable == USB_HAUDIO_YES )
        {
            usb0_api_haudio_stream_out_stop_link( devadr );
        }

        usb0_haudio_SetDevDetachSts(devadr);
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_stream_in_check_sample_rate
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_in_check_sample_rate( uint16_t devadr,
                                                     uint32_t sample_rate  )
{
    uint8_t    loop;

    if( usb0_haudio_GetDevSts(devadr) == USB_HAUDIO_DEV_DET )
    {
        return USB_HAUDIO_ERROR;
    }

    if( g_usb0_haudio[ devadr ].StreamIn.PipeNum == USB_HAUDIO_INVALID )
    {
        return USB_HAUDIO_ERROR;
    }

    for( loop = 0; loop < g_usb0_haudio[ devadr ].StreamIn.Sample_Num; loop++ )
    {
        if( sample_rate == g_usb0_haudio[ devadr ].StreamIn.Sample_Rate[ loop ] )
        {
            return USB_HAUDIO_SUCCESS;
        }
    }

    /* not support sampling rate */
    return USB_HAUDIO_ERROR;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_stream_in_start_link
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_in_start_link( uint16_t devadr,
                                              uint32_t sample_rate,
                                              uint8_t *buf_adr,
                                              uint32_t buf_size     )
{
    int32_t     ret;
    uint8_t     buf[4];
    uint8_t     buf_r[4];
    uint16_t    wIndex;
    uint32_t    sample;
    uint32_t    sample_buf_size;
    int32_t     set_cur_flag;

    if( usb0_haudio_GetDevSts(devadr) == USB_HAUDIO_DEV_DET )
    {
        return USB_HAUDIO_ERROR;
    }

    if( g_usb0_haudio[ devadr ].StreamIn.PipeNum == USB_HAUDIO_INVALID )
    {
        return USB_HAUDIO_ERROR;
    }

    if( usb0_api_haudio_stream_in_check_sample_rate( devadr, sample_rate ) != USB_HAUDIO_SUCCESS )
    {
        /* not support sampling rate */
        return USB_HAUDIO_TYPE_ERROR;
    }

    wIndex = g_usb0_haudio[ devadr ].StreamIn.EndPointAddress;
    buf[0] = (uint8_t)((sample_rate >>  0) & 0xff);
    buf[1] = (uint8_t)((sample_rate >>  8) & 0xff);
    buf[2] = (uint8_t)((sample_rate >> 16) & 0xff);
    buf[3] = (uint8_t)((sample_rate >> 24) & 0xff);
    ret = usb0_api_haudio_stream_SetCur( devadr, USB_HAUDIO_SAMPLING, wIndex, buf, 3 );
    if( ret == USB_HAUDIO_SUCCESS )
    {
        set_cur_flag = USB_HAUDIO_YES;
    }
    else
    {
        set_cur_flag = USB_HAUDIO_NO;
    }

    /* set interface stream-in pipe */
    ret = usb0_api_class_SetInterface( devadr,
                                       g_usb0_haudio[ devadr ].StreamIn.OnAltNum,
                                       g_usb0_haudio[ devadr ].StreamIn.Interface );
    if(ret != USB_SUCCESS)
    {
        return ret;
    }
    wIndex = g_usb0_haudio[ devadr ].StreamIn.EndPointAddress;
    buf_r[0] = 0;
    buf_r[1] = 0;
    buf_r[2] = 0;
    buf_r[3] = 0;
    ret = usb0_api_haudio_stream_GetCur( devadr, USB_HAUDIO_SAMPLING, wIndex, buf_r, 3 );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        if( set_cur_flag == USB_HAUDIO_NO )
        {
            return USB_HAUDIO_TYPE_ERROR;

        }

        /* dont care continue */
        sample = sample_rate;
    }
    else
    {
        sample = ( ((buf_r[0] <<  0) & 0x000000ff) |
                   ((buf_r[1] <<  8) & 0x0000ff00) |
                   ((buf_r[2] << 16) & 0x00ff0000) |
                   ((buf_r[3] << 24) & 0xff000000)   );
    }

    if( sample != sample_rate )
    {
        /* cannot set up sampling rate */
        return USB_HAUDIO_TYPE_ERROR;
    }

    sample_buf_size = ((sample * 4) / (1000 / USB_HAUDIO_LINK_COUNT));
    sample_buf_size *= USB_HAUDIO_LINK_CHANGE;
    if( sample_buf_size > buf_size )
    {
        return USB_HAUDIO_TYPE_ERROR;
    }

    /* change link table regarding of sample_rate */
    if( g_usb0_haudio[ devadr ].StreamIn.FifoPort == USB_D0DMA )
    {
        usb0_make_dmac0_link_table (USB_FIFO2BUF, buf_adr, sample_buf_size, buf_size);
    }
    else
    {
        usb0_make_dmac1_link_table (USB_FIFO2BUF, buf_adr, sample_buf_size, buf_size);
    }

    /* set stream in pipe table */
    ret = usb0_api_hcd_change_endpoint( g_usb0_haudio[ devadr ].audio_regist->pipe_table,
                                        g_usb0_haudio[ devadr ].StreamIn.PipeNum );
    if(ret != USB_SUCCESS)
    {
        return ret;
    }

    usb0_userdef_os_dly_tsk(10);

    g_usb0_haudio[ devadr ].StreamIn.pipe_enable = USB_HAUDIO_YES;

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_stream_in_stop_link
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_in_stop_link(uint16_t devadr)
{
    int32_t    ret;

    if( usb0_haudio_GetDevSts(devadr) == USB_HAUDIO_DEV_DET )
    {
        return USB_HAUDIO_ERROR;
    }

    if( g_usb0_haudio[ devadr ].StreamIn.PipeNum == USB_HAUDIO_INVALID )
    {
        return USB_HAUDIO_ERROR;
    }

    if( g_usb0_haudio[ devadr ].StreamIn.pipe_enable == USB_HAUDIO_NO )
    {
        return USB_HAUDIO_ERROR;
    }
    g_usb0_haudio[ devadr ].StreamIn.pipe_enable = USB_HAUDIO_NO;

    usb0_api_hcd_force_end( g_usb0_haudio[ devadr ].StreamIn.PipeNum );

    /* disable interface stream-in pipe */
    if( g_usb0_haudio[ devadr ].StreamIn.OffAltNum != USB_HAUDIO_INVALID )
    {
        ret = usb0_api_class_SetInterface( devadr,
                                           g_usb0_haudio[ devadr ].StreamIn.OffAltNum,
                                           g_usb0_haudio[ devadr ].StreamIn.Interface );
        if(ret != USB_SUCCESS)
        {
            return ret;
        }
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_stream_in_link
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_in_link( uint16_t devadr )
{
    int32_t    ret;

    if( usb0_haudio_GetDevSts(devadr) == USB_HAUDIO_DEV_DET )
    {
        return USB_HAUDIO_ERROR;
    }

    if( g_usb0_haudio[ devadr ].StreamIn.PipeNum == USB_HAUDIO_INVALID )
    {
        return USB_HAUDIO_ERROR;
    }

    g_usb0_AudioIn_ISO.devadr           = devadr;
    g_usb0_AudioIn_ISO.transfer_address = (void *)0;
    g_usb0_AudioIn_ISO.complete_proc    = (USB_CALLBACK_HCD_REQUEST)0;
    g_usb0_AudioIn_ISO.transfer_length  = 0;
    g_usb0_AudioIn_ISO.pipe_number      = (uint16_t)g_usb0_haudio[ devadr ].StreamIn.PipeNum;
    g_usb0_AudioIn_ISO.setup_packet     = 0;
    g_usb0_AudioIn_ISO.bit_size         = USB_ISO_32BIT;
    g_usb0_AudioIn_ISO.reload_address   = (void *)0;
    g_usb0_AudioIn_ISO.reload_length    = 0;

    ret = usb0_api_hcd_request_iso_link( &g_usb0_AudioIn_ISO );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        return USB_HAUDIO_ERROR;
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_stream_in_wait_link
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_in_wait_link( uint16_t devadr, int32_t index )
{
    int32_t    ret;
    int32_t    task_ofst;

    if( index >= USB_HAUDIO_LINK_CHANGE )
    {
        return USB_HAUDIO_ERROR;
    }

    if( usb0_haudio_GetDevSts(devadr) == USB_HAUDIO_DEV_DET )
    {
        return USB_HAUDIO_ERROR;
    }

    if( g_usb0_haudio[ devadr ].StreamIn.PipeNum == USB_HAUDIO_INVALID )
    {
        return USB_HAUDIO_ERROR;
    }

    if( g_usb0_haudio[ devadr ].StreamIn.FifoPort == USB_D0DMA )
    {
        ret = usb0_userdef_os_set_signal_tskid(USB_D0FIFO, &task_ofst);
        if( ret != USB_SUCCESS )
        {
            return USB_HAUDIO_ERROR;
        }

        while(1)
        {
            ret = usb0_userdef_os_wait_signal(USB_D0FIFO, g_usb0_haudio[ devadr ].audio_regist->time_out);
            if( ret != USB_SUCCESS )
            {
                return USB_HAUDIO_ERROR;
            }

            ret = usb0_check_interrupt_index_0_iso( index );
            if( ret == USB_SUCCESS )
            {
                break;
            }
        }

        ret = usb0_userdef_os_clear_signal_tskid(USB_D0FIFO, task_ofst);
        if( ret != USB_SUCCESS )
        {
            return USB_HAUDIO_ERROR;
        }
    }
    else
    {
        ret = usb0_userdef_os_set_signal_tskid(USB_D1FIFO, &task_ofst);
        if( ret != USB_SUCCESS )
        {
            return USB_HAUDIO_ERROR;
        }

        while(1)
        {
            ret = usb0_userdef_os_wait_signal(USB_D1FIFO, g_usb0_haudio[ devadr ].audio_regist->time_out);
            if( ret != USB_SUCCESS )
            {
                return USB_HAUDIO_ERROR;
            }

            ret = usb0_check_interrupt_index_1_iso( index );
            if( ret == USB_SUCCESS )
            {
                break;
            }
        }

        ret = usb0_userdef_os_clear_signal_tskid(USB_D1FIFO, task_ofst);
        if( ret != USB_SUCCESS )
        {
            return USB_HAUDIO_ERROR;
        }
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_stream_out_check_sample_rate
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_out_check_sample_rate( uint16_t devadr,
                                                      uint32_t sample_rate  )
{
    uint8_t    loop;

    if( usb0_haudio_GetDevSts(devadr) == USB_HAUDIO_DEV_DET )
    {
        return USB_HAUDIO_ERROR;
    }

    if( g_usb0_haudio[ devadr ].StreamOut.PipeNum == USB_HAUDIO_INVALID )
    {
        return USB_HAUDIO_ERROR;
    }

    for( loop = 0; loop < g_usb0_haudio[ devadr ].StreamOut.Sample_Num; loop++ )
    {
        if( sample_rate == g_usb0_haudio[ devadr ].StreamOut.Sample_Rate[ loop ] )
        {
            return USB_HAUDIO_SUCCESS;
        }
    }

    /* not support sampling rate */
    return USB_HAUDIO_ERROR;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_stream_out_start_link
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_out_start_link( uint16_t devadr,
                                               uint32_t sample_rate,
                                               uint8_t *buf_adr,
                                               uint32_t buf_size,
                                               uint32_t *output_format     )
{
    int32_t     ret;
    uint8_t     buf[4];
    uint8_t     buf_r[4];
    uint16_t    wIndex;
    uint16_t    entity;
    uint32_t    sample;
    uint32_t    sample_buf_size;
    int32_t     set_cur_flag;


    if( usb0_haudio_GetDevSts(devadr) == USB_HAUDIO_DEV_DET )
    {
        return USB_HAUDIO_ERROR;
    }

    if( g_usb0_haudio[ devadr ].StreamOut.PipeNum == USB_HAUDIO_INVALID )
    {
        return USB_HAUDIO_ERROR;
    }
    if(g_usb0_haudio[ devadr ].AudioSrc.SrcId != 0)
    {
        wIndex = (uint16_t)(g_usb0_haudio[ devadr ].AudioSrc.ClockSrcId << 8);
        buf[0] = (uint8_t)((sample_rate >>  0) & 0xff);
        buf[1] = (uint8_t)((sample_rate >>  8) & 0xff);
        buf[2] = (uint8_t)((sample_rate >> 16) & 0xff);
        buf[3] = (uint8_t)((sample_rate >> 24) & 0xff);
        ret = usb0_api_haudio_control_SetCur( devadr, USB_HAUDIO_SAMPLING, wIndex, buf, 4 );
        if( ret == USB_HAUDIO_SUCCESS )
        {
            set_cur_flag = USB_HAUDIO_YES;
        }
        else
        {
            set_cur_flag = USB_HAUDIO_NO;
        }
        /* set interface stream-out pipe */
        ret = usb0_api_class_SetInterface( devadr,
                                           g_usb0_haudio[ devadr ].StreamOut.OnAltNum,
                                           g_usb0_haudio[ devadr ].StreamOut.Interface );

        if(ret != USB_SUCCESS)
        {
            return ret;
        }
    }
    else
    {
        /* set interface stream-out pipe */
        ret = usb0_api_class_SetInterface( devadr,
                                           g_usb0_haudio[ devadr ].StreamOut.OnAltNum,
                                           g_usb0_haudio[ devadr ].StreamOut.Interface );
        if(ret != USB_SUCCESS)
        {
            return ret;
        }
        wIndex = g_usb0_haudio[ devadr ].StreamOut.EndPointAddress;
        buf[0] = (uint8_t)((sample_rate >>  0) & 0xff);
        buf[1] = (uint8_t)((sample_rate >>  8) & 0xff);
        buf[2] = (uint8_t)((sample_rate >> 16) & 0xff);
        buf[3] = (uint8_t)((sample_rate >> 24) & 0xff);
        ret = usb0_api_haudio_stream_SetCur( devadr, USB_HAUDIO_SAMPLING, wIndex, buf, 3 );
        if( ret == USB_HAUDIO_SUCCESS )
        {
            set_cur_flag = USB_HAUDIO_YES;
        }
        else
        {
            set_cur_flag = USB_HAUDIO_NO;
        }
    }

    if(g_usb0_haudio[ devadr ].AudioSrc.SrcId != 0)
    {
        wIndex = (uint16_t)(g_usb0_haudio[ devadr ].AudioSrc.ClockSrcId << 8);
        buf_r[0] = 0;
        buf_r[1] = 0;
        buf_r[2] = 0;
        buf_r[3] = 0;
        ret = usb0_api_haudio_control_GetCur_20( devadr, USB_HAUDIO_SAMPLING, wIndex, buf_r, 4 );
    }
    else
    {
        wIndex = g_usb0_haudio[ devadr ].StreamOut.EndPointAddress;
        buf_r[0] = 0;
        buf_r[1] = 0;
        buf_r[2] = 0;
        buf_r[3] = 0;
        ret = usb0_api_haudio_stream_GetCur( devadr, USB_HAUDIO_SAMPLING, wIndex, buf_r, 3 );
    }
    if( ret != USB_HAUDIO_SUCCESS )
    {
        if( set_cur_flag == USB_HAUDIO_NO )
        {
            return USB_HAUDIO_TYPE_ERROR;

        }

        /* dont care continue */
        sample = sample_rate;
    }
    else
    {
        /* 使用するデバイスによって返す値が異なるため */
        /* #defineにて値を定義する */
        sample = ( ((buf_r[0] <<  0) & 0x000000ff) |
                   ((buf_r[1] <<  8) & 0x0000ff00) |
                   ((buf_r[2] << 16) & 0x00ff0000)   );
        printf("Sampling Rate of your audio device is 0x%06x \n", sample);

        sample = USB_USER_SAMPLE_RATE;
    }
    if( sample != sample_rate )
    {
        /* cannot set up sampling rate */
        return USB_HAUDIO_TYPE_ERROR;
    }

    sample_buf_size = ((sample * g_usb0_haudio[ devadr ].StreamOut.SubframeSize * 2) / (1000 / USB_HAUDIO_LINK_COUNT));
    sample_buf_size *= USB_HAUDIO_LINK_CHANGE;
    if( sample_buf_size > buf_size )
    {
        printf("USB_HAUDIO_ERROR \n");
        printf("Change the macro named USB_USER_SAMPLE_RATE \n\n");
        return USB_HAUDIO_ERROR;
    }

    /* change link table regarding of sample_rate */
    if( g_usb0_haudio[ devadr ].StreamOut.FifoPort == USB_D0DMA )
    {
        usb0_make_dmac0_link_table (USB_BUF2FIFO, buf_adr, sample_buf_size, buf_size);
    }
    else
    {
        usb0_make_dmac1_link_table (USB_BUF2FIFO, buf_adr, sample_buf_size, buf_size);
    }

    /* set stream out pipe table */
    ret = usb0_api_hcd_change_endpoint( g_usb0_haudio[ devadr ].audio_regist->pipe_table,
                                        g_usb0_haudio[ devadr ].StreamOut.PipeNum );
    if(ret != USB_SUCCESS)
    {
        return ret;
    }

    if(g_usb0_haudio[ devadr ].StreamOut.BitResolution == 16)
    {
        *output_format = USB_HAUDIO_16BPS;
    }
    else if(g_usb0_haudio[ devadr ].StreamOut.BitResolution == 24)
    {
        if(g_usb0_haudio[ devadr ].StreamOut.SubframeSize == 3)
        {
            *output_format = USB_HAUDIO_24BPS;
        }
        else if (g_usb0_haudio[ devadr ].StreamOut.SubframeSize == 4)
        {
            *output_format = USB_HAUDIO_24BPS_WITH_PAD;
        }
        else
        {
            *output_format = USB_HAUDIO_24BPS;
        }
    }
    else
    {
        *output_format = USB_HAUDIO_16BPS;
    }

    usb0_userdef_os_dly_tsk(10);

    g_usb0_haudio[ devadr ].StreamOut.pipe_enable = USB_HAUDIO_YES;

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_stream_out_stop_link
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_out_stop_link(uint16_t devadr)
{
    int32_t    ret;

    if( usb0_haudio_GetDevSts(devadr) == USB_HAUDIO_DEV_DET )
    {
        return USB_HAUDIO_ERROR;
    }

    if( g_usb0_haudio[ devadr ].StreamOut.PipeNum == USB_HAUDIO_INVALID )
    {
        return USB_HAUDIO_ERROR;
    }

    if( g_usb0_haudio[ devadr ].StreamOut.pipe_enable == USB_HAUDIO_NO )
    {
        return USB_HAUDIO_ERROR;
    }
    g_usb0_haudio[ devadr ].StreamOut.pipe_enable = USB_HAUDIO_NO;

    usb0_api_hcd_force_end( g_usb0_haudio[ devadr ].StreamOut.PipeNum );

    /* disable interface stream-in pipe */
    if( g_usb0_haudio[ devadr ].StreamOut.OffAltNum != USB_HAUDIO_INVALID )
    {
        ret = usb0_api_class_SetInterface( devadr,
                                           g_usb0_haudio[ devadr ].StreamOut.OffAltNum,
                                           g_usb0_haudio[ devadr ].StreamOut.Interface );
        if(ret != USB_SUCCESS)
        {
            return ret;
        }
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_stream_out_link
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_out_link(uint16_t devadr)
{
    int32_t        ret;

    if( usb0_haudio_GetDevSts(devadr) == USB_HAUDIO_DEV_DET )
    {
        return USB_HAUDIO_ERROR;
    }

    if( g_usb0_haudio[ devadr ].StreamOut.PipeNum == USB_HAUDIO_INVALID )
    {
        return USB_HAUDIO_ERROR;
    }

    g_usb0_AudioOut_ISO.devadr           = devadr;
    g_usb0_AudioOut_ISO.transfer_address = (void *)0;
    g_usb0_AudioOut_ISO.complete_proc    = (USB_CALLBACK_HCD_REQUEST)0;
    g_usb0_AudioOut_ISO.transfer_length  = 0;
    g_usb0_AudioOut_ISO.pipe_number      = (uint16_t)g_usb0_haudio[ devadr ].StreamOut.PipeNum;
    g_usb0_AudioOut_ISO.setup_packet     = 0;
    g_usb0_AudioOut_ISO.bit_size         = USB_ISO_32BIT;
    g_usb0_AudioOut_ISO.reload_address   = (void *)0;
    g_usb0_AudioOut_ISO.reload_length    = 0;

    ret = usb0_api_hcd_request_iso_link( &g_usb0_AudioOut_ISO );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        return USB_HAUDIO_ERROR;
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_stream_out_wait_link
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_out_wait_link(uint16_t devadr, int32_t index)
{
    int32_t    ret;
    int32_t    task_ofst;

    if( index >= USB_HAUDIO_LINK_CHANGE )
    {
        return USB_HAUDIO_ERROR;
    }

    if( usb0_haudio_GetDevSts(devadr) == USB_HAUDIO_DEV_DET )
    {
        return USB_HAUDIO_ERROR;
    }

    if( g_usb0_haudio[ devadr ].StreamOut.PipeNum == USB_HAUDIO_INVALID )
    {
        return USB_HAUDIO_ERROR;
    }

    if( g_usb0_haudio[ devadr ].StreamOut.FifoPort == USB_D0DMA )
    {
        ret = usb0_userdef_os_set_signal_tskid(USB_D0FIFO, &task_ofst);
        if( ret != USB_SUCCESS )
        {
            return USB_HAUDIO_ERROR;
        }

        while(1)
        {
            ret = usb0_userdef_os_wait_signal(USB_D0FIFO, g_usb0_haudio[ devadr ].audio_regist->time_out);
            if( ret != USB_SUCCESS )
            {
                return USB_HAUDIO_ERROR;
            }

            ret = usb0_check_interrupt_index_0_iso( index );
            if( ret == USB_SUCCESS )
            {
                break;
            }
        }

        ret = usb0_userdef_os_clear_signal_tskid(USB_D0FIFO, task_ofst);
        if( ret != USB_SUCCESS )
        {
            return USB_HAUDIO_ERROR;
        }
    }
    else
    {
        ret = usb0_userdef_os_set_signal_tskid(USB_D1FIFO, &task_ofst);
        if( ret != USB_SUCCESS )
        {
            return USB_HAUDIO_ERROR;
        }

        while(1)
        {
            ret = usb0_userdef_os_wait_signal(USB_D1FIFO, g_usb0_haudio[ devadr ].audio_regist->time_out);
            if( ret != USB_SUCCESS )
            {
                return USB_HAUDIO_ERROR;
            }

            ret = usb0_check_interrupt_index_1_iso( index );
            if( ret == USB_SUCCESS )
            {
                break;
            }
        }

        ret = usb0_userdef_os_clear_signal_tskid(USB_D1FIFO, task_ofst);
        if( ret != USB_SUCCESS )
        {
            return USB_HAUDIO_ERROR;
        }
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_stream_in_start
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_in_start(uint16_t devadr, uint32_t sample_rate)
{
    int32_t     ret;
    uint8_t     buf[4];
    uint8_t     buf_r[4];
    uint16_t    wIndex;
    uint32_t    sample;
    int32_t     set_cur_flag;

    if( usb0_haudio_GetDevSts(devadr) == USB_HAUDIO_DEV_DET )
    {
        return USB_HAUDIO_ERROR;
    }

    if( g_usb0_haudio[ devadr ].StreamIn.PipeNum == USB_HAUDIO_INVALID )
    {
        return USB_HAUDIO_ERROR;
    }

    if( usb0_api_haudio_stream_in_check_sample_rate( devadr, sample_rate ) != USB_HAUDIO_SUCCESS )
    {
        /* not support sampling rate */
        return USB_HAUDIO_TYPE_ERROR;
    }

    while(1)
    {
        ret = usb0_haudio_in_wait(devadr, 1);
        if( ret == USB_HAUDIO_NAK_TIMEOUT )
        {
            break;
        }
    }

    /* set interface stream-in pipe */
    ret = usb0_api_class_SetInterface( devadr,
                                       g_usb0_haudio[ devadr ].StreamIn.OnAltNum,
                                       g_usb0_haudio[ devadr ].StreamIn.Interface );
    if(ret != USB_SUCCESS)
    {
        return ret;
    }
    wIndex = g_usb0_haudio[ devadr ].StreamIn.EndPointAddress;
    buf[0] = (uint8_t)((sample_rate >>  0) & 0xff);
    buf[1] = (uint8_t)((sample_rate >>  8) & 0xff);
    buf[2] = (uint8_t)((sample_rate >> 16) & 0xff);
    buf[3] = (uint8_t)((sample_rate >> 24) & 0xff);
    ret = usb0_api_haudio_stream_SetCur( devadr, USB_HAUDIO_SAMPLING, wIndex, buf, 3 );
    if( ret == USB_HAUDIO_SUCCESS )
    {
        set_cur_flag = USB_HAUDIO_YES;
    }
    else
    {
        set_cur_flag = USB_HAUDIO_NO;
    }

    wIndex = g_usb0_haudio[ devadr ].StreamIn.EndPointAddress;
    buf_r[0] = 0;
    buf_r[1] = 0;
    buf_r[2] = 0;
    buf_r[3] = 0;
    ret = usb0_api_haudio_stream_GetCur( devadr, USB_HAUDIO_SAMPLING, wIndex, buf_r, 3 );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        if( set_cur_flag == USB_HAUDIO_NO )
        {
            return USB_HAUDIO_TYPE_ERROR;

        }

        /* dont care continue */
        sample = sample_rate;
    }
    else
    {
        sample = ( ((buf_r[0] <<  0) & 0x000000ff) |
                   ((buf_r[1] <<  8) & 0x0000ff00) |
                   ((buf_r[2] << 16) & 0x00ff0000) |
                   ((buf_r[3] << 24) & 0xff000000)   );
    }

    if( sample != sample_rate )
    {
        /* cannot set up sampling rate */
        return USB_HAUDIO_TYPE_ERROR;
    }

    /* set stream in pipe table */
    ret = usb0_api_hcd_change_endpoint( g_usb0_haudio[ devadr ].audio_regist->pipe_table,
                                        g_usb0_haudio[ devadr ].StreamIn.PipeNum );
    if(ret != USB_SUCCESS)
    {
        return ret;
    }

    usb0_userdef_os_dly_tsk(10);

    g_usb0_haudio[ devadr ].StreamIn.pipe_enable = USB_HAUDIO_YES2;

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_stream_in_stop
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_in_stop(uint16_t devadr)
{
    int32_t    ret;

    if( usb0_haudio_GetDevSts(devadr) == USB_HAUDIO_DEV_DET )
    {
        return USB_HAUDIO_ERROR;
    }

    if( g_usb0_haudio[ devadr ].StreamIn.PipeNum == USB_HAUDIO_INVALID )
    {
        return USB_HAUDIO_ERROR;
    }

    if( g_usb0_haudio[ devadr ].StreamIn.pipe_enable == USB_HAUDIO_NO )
    {
        return USB_HAUDIO_ERROR;
    }
    g_usb0_haudio[ devadr ].StreamIn.pipe_enable = USB_HAUDIO_NO;

    usb0_api_hcd_force_end( g_usb0_haudio[ devadr ].StreamIn.PipeNum );

    while(1)
    {
        ret = usb0_haudio_in_wait(devadr, 1);
        if( ret == USB_HAUDIO_NAK_TIMEOUT )
        {
            break;
        }
    }

    /* disable interface stream-in pipe */
    if( g_usb0_haudio[ devadr ].StreamIn.OffAltNum != USB_HAUDIO_INVALID )
    {
        ret = usb0_api_class_SetInterface( devadr,
                                           g_usb0_haudio[ devadr ].StreamIn.OffAltNum,
                                           g_usb0_haudio[ devadr ].StreamIn.Interface );
        if(ret != USB_SUCCESS)
        {
            return ret;
        }
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_stream_in
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_in( uint16_t devadr,
                                   uint8_t *buf_adr,
                                   uint32_t buf_size,
                                   uint8_t *reload_buf_adr,
                                   uint32_t reload_buf_size )
{
    int32_t    ret;

    if( usb0_haudio_GetDevSts(devadr) == USB_HAUDIO_DEV_DET )
    {
        return USB_HAUDIO_ERROR;
    }

    if( g_usb0_haudio[ devadr ].StreamIn.PipeNum == USB_HAUDIO_INVALID )
    {
        return USB_HAUDIO_ERROR;
    }

    g_usb0_haudio[ devadr ].StreamIn.CurrentBuff      = buf_adr;
    g_usb0_haudio[ devadr ].StreamIn.CurrentSize      = 0;
    g_usb0_haudio[ devadr ].StreamIn.CurrentCount     = 0;
    g_usb0_haudio[ devadr ].StreamIn.TransSize        = buf_size;

    g_usb0_haudio[ devadr ].StreamIn.ReloadBuff      = reload_buf_adr;
    g_usb0_haudio[ devadr ].StreamIn.ReloadSize      = 0;
    g_usb0_haudio[ devadr ].StreamIn.ReloadCount     = 0;
    g_usb0_haudio[ devadr ].StreamIn.ReloadTransSize = reload_buf_size;

    g_usb0_AudioIn_ISO.devadr           = devadr;
    g_usb0_AudioIn_ISO.transfer_address = (void *)buf_adr;
    g_usb0_AudioIn_ISO.complete_proc    = (USB_CALLBACK_HCD_REQUEST)&usb0_haudio_in_hcd_request_result;
    g_usb0_AudioIn_ISO.transfer_length  = buf_size;
    g_usb0_AudioIn_ISO.pipe_number      = (uint16_t)g_usb0_haudio[ devadr ].StreamIn.PipeNum;
    g_usb0_AudioIn_ISO.setup_packet     = 0;
    g_usb0_AudioIn_ISO.bit_size         = USB_ISO_32BIT;
    g_usb0_AudioIn_ISO.reload_address   = (void *)reload_buf_adr;
    g_usb0_AudioIn_ISO.reload_length    = reload_buf_size;

    ret = usb0_api_hcd_request_iso( &g_usb0_AudioIn_ISO );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        return USB_HAUDIO_ERROR;
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_stream_in_wait
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_in_wait( uint16_t devadr, uint32_t *real_size,
                                        uint8_t *reload_buff, uint32_t reload_size )
{
    int32_t    ret;

    if( usb0_haudio_GetDevSts(devadr) == USB_HAUDIO_DEV_DET )
    {
        return USB_HAUDIO_ERROR;
    }

    if( g_usb0_haudio[ devadr ].StreamIn.PipeNum == USB_HAUDIO_INVALID )
    {
        return USB_HAUDIO_ERROR;
    }

    g_usb0_haudio[ devadr ].StreamIn.ReloadBuff      = reload_buff;
    g_usb0_haudio[ devadr ].StreamIn.ReloadSize      = 0;
    g_usb0_haudio[ devadr ].StreamIn.ReloadCount     = 0;
    g_usb0_haudio[ devadr ].StreamIn.ReloadTransSize = reload_size;

    ret = usb0_haudio_in_wait( devadr, g_usb0_haudio[ devadr ].audio_regist->time_out );
    if( ret == USB_HCD_DATA_OK )
    {
        *real_size = g_usb0_haudio[ devadr ].StreamIn.CurrentSize;
        ret = USB_HAUDIO_SUCCESS;
    }

    if( ret == USB_HCD_DATA_STALL )
    {
        ret = USB_HAUDIO_STALL;
    }
    else if( ret == USB_HCD_DATA_DETACH )
    {
        ret = USB_HAUDIO_DETACH;
    }
    else if( ret == USB_HAUDIO_NAK_TIMEOUT )
    {
        ret = USB_HAUDIO_NAK_TIMEOUT;
    }
    else if( ret == USB_HCD_PIPE_ISO_COM_ERR )
    {
        ret = USB_HAUDIO_COM_ERR;
    }
    else if( ret == USB_HCD_PIPE_COM_ERR )
    {
        ret = USB_HAUDIO_COM_ERR;
    }

    return ret;
}




/*========================= Audio Standard Request =========================*/
/*******************************************************************************
* Function Name: usb0_api_haudio_control_GetCur
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_control_GetCur(uint16_t devadr, uint16_t wValue, uint16_t wIndex,
                                       uint8_t *buff, uint16_t size                       )
{
    uint16_t    Req_Table[ 4 ];
    int32_t     ret;

    Req_Table[ 0 ] = ( USB_HAUDIO_GET_CUR        |
                       USB_HAUDIO_DEVICE_TO_HOST |
                       USB_HAUDIO_REQ_CLASS      |
                       USB_HAUDIO_INTERFACE        );
    Req_Table[ 1 ] = wValue;
    Req_Table[ 2 ] = wIndex;
    Req_Table[ 3 ] = size;

    ret = usb0_api_class_request( devadr, &Req_Table[ 0 ], buff );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        return ret;
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_control_GetCur20
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_control_GetCur_20(uint16_t devadr, uint16_t wValue, uint16_t wIndex,
                                       uint8_t *buff, uint16_t size                       )
{
    uint16_t    Req_Table[ 4 ];
    int32_t     ret;

    Req_Table[ 0 ] = ( USB_HAUDIO_SET_CUR        |
                       USB_HAUDIO_DEVICE_TO_HOST |
                       USB_HAUDIO_REQ_CLASS      |
                       USB_HAUDIO_INTERFACE        );
    Req_Table[ 1 ] = wValue;
    Req_Table[ 2 ] = wIndex;
    Req_Table[ 3 ] = size;

    ret = usb0_api_class_request( devadr, &Req_Table[ 0 ], buff );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        return ret;
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_control_GetMin
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_control_GetMin(uint16_t devadr, uint16_t wValue, uint16_t wIndex,
                                       uint8_t *buff, uint16_t size                       )
{
    uint16_t    Req_Table[ 4 ];
    int32_t     ret;

    Req_Table[ 0 ] = ( USB_HAUDIO_GET_MIN        |
                       USB_HAUDIO_DEVICE_TO_HOST |
                       USB_HAUDIO_REQ_CLASS      |
                       USB_HAUDIO_INTERFACE        );
    Req_Table[ 1 ] = wValue;
    Req_Table[ 2 ] = wIndex;
    Req_Table[ 3 ] = size;

    ret = usb0_api_class_request( devadr, &Req_Table[ 0 ], buff );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        return ret;
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_control_GetMax
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_control_GetMax(uint16_t devadr, uint16_t wValue, uint16_t wIndex,
                                       uint8_t *buff, uint16_t size                       )
{
    uint16_t    Req_Table[ 4 ];
    int32_t     ret;

    Req_Table[ 0 ] = ( USB_HAUDIO_GET_MAX        |
                       USB_HAUDIO_DEVICE_TO_HOST |
                       USB_HAUDIO_REQ_CLASS      |
                       USB_HAUDIO_INTERFACE        );
    Req_Table[ 1 ] = wValue;
    Req_Table[ 2 ] = wIndex;
    Req_Table[ 3 ] = size;

    ret = usb0_api_class_request( devadr, &Req_Table[ 0 ], buff );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        return ret;
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_control_GetRes
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_control_GetRes(uint16_t devadr, uint16_t wValue, uint16_t wIndex,
                                       uint8_t *buff, uint16_t size                       )
{
    uint16_t    Req_Table[ 4 ];
    int32_t     ret;

    Req_Table[ 0 ] = ( USB_HAUDIO_GET_RES        |
                       USB_HAUDIO_DEVICE_TO_HOST |
                       USB_HAUDIO_REQ_CLASS      |
                       USB_HAUDIO_INTERFACE        );
    Req_Table[ 1 ] = wValue;
    Req_Table[ 2 ] = wIndex;
    Req_Table[ 3 ] = size;

    ret = usb0_api_class_request( devadr, &Req_Table[ 0 ], buff );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        return ret;
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_control_SetCur
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_control_SetCur(uint16_t devadr, uint16_t wValue, uint16_t wIndex,
                                       uint8_t *buff, uint16_t size                       )
{
    uint16_t    Req_Table[ 4 ];
    int32_t     ret;

    Req_Table[ 0 ]  = ( USB_HAUDIO_SET_CUR        |
                        USB_HAUDIO_HOST_TO_DEVICE |
                        USB_HAUDIO_REQ_CLASS      |
                        USB_HAUDIO_INTERFACE        );
    Req_Table[ 1 ] = wValue;
    Req_Table[ 2 ] = wIndex;
    Req_Table[ 3 ] = size;

    ret = usb0_api_class_request( devadr, &Req_Table[ 0 ], buff );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        return ret;
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_control_SetMin
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_control_SetMin(uint16_t devadr, uint16_t wValue, uint16_t wIndex,
                                       uint8_t *buff, uint16_t size                       )
{
    uint16_t    Req_Table[ 4 ];
    int32_t     ret;

    Req_Table[ 0 ] = ( USB_HAUDIO_SET_MIN        |
                       USB_HAUDIO_HOST_TO_DEVICE |
                       USB_HAUDIO_REQ_CLASS      |
                       USB_HAUDIO_INTERFACE        );
    Req_Table[ 1 ] = wValue;
    Req_Table[ 2 ] = wIndex;
    Req_Table[ 3 ] = size;

    ret = usb0_api_class_request( devadr, &Req_Table[ 0 ], buff );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        return ret;
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_control_SetMax
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_control_SetMax(uint16_t devadr, uint16_t wValue, uint16_t wIndex,
                                       uint8_t *buff, uint16_t size                       )
{
    uint16_t    Req_Table[ 4 ];
    int32_t     ret;

    Req_Table[ 0 ] = ( USB_HAUDIO_SET_MAX        |
                       USB_HAUDIO_HOST_TO_DEVICE |
                       USB_HAUDIO_REQ_CLASS      |
                       USB_HAUDIO_INTERFACE        );
    Req_Table[ 1 ] = wValue;
    Req_Table[ 2 ] = wIndex;
    Req_Table[ 3 ] = size;

    ret = usb0_api_class_request( devadr, &Req_Table[ 0 ], buff );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        return ret;
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_control_SetRes
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_control_SetRes(uint16_t devadr, uint16_t wValue, uint16_t wIndex,
                                       uint8_t *buff, uint16_t size                       )
{
    uint16_t    Req_Table[ 4 ];
    int32_t     ret;

    Req_Table[ 0 ] = ( USB_HAUDIO_SET_RES        |
                       USB_HAUDIO_HOST_TO_DEVICE |
                       USB_HAUDIO_REQ_CLASS      |
                       USB_HAUDIO_INTERFACE        );
    Req_Table[ 1 ] = wValue;
    Req_Table[ 2 ] = wIndex;
    Req_Table[ 3 ] = size;

    ret = usb0_api_class_request( devadr, &Req_Table[ 0 ], buff );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        return ret;
    }

    return USB_HAUDIO_SUCCESS;
}

/*========================== Audio Steram Request ==========================*/
/*******************************************************************************
* Function Name: usb0_api_haudio_stream_GetCur
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_GetCur(uint16_t devadr, uint16_t wValue, uint16_t wIndex,
                                      uint8_t *buff, uint16_t size                        )
{
    uint16_t    Req_Table[ 4 ];
    int32_t     ret;

    Req_Table[ 0 ] = ( USB_HAUDIO_GET_CUR        |
                       USB_HAUDIO_DEVICE_TO_HOST |
                       USB_HAUDIO_REQ_CLASS      |
                       USB_HAUDIO_ENDPOINT         );
    Req_Table[ 1 ] = wValue;
    Req_Table[ 2 ] = wIndex;
    Req_Table[ 3 ] = size;

    ret = usb0_api_class_request( devadr, &Req_Table[ 0 ], buff );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        return ret;
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_stream_GetMin
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_GetMin(uint16_t devadr, uint16_t wValue, uint16_t wIndex,
                                      uint8_t *buff, uint16_t size                        )
{
    uint16_t    Req_Table[ 4 ];
    int32_t     ret;

    Req_Table[ 0 ] = ( USB_HAUDIO_GET_MIN        |
                       USB_HAUDIO_DEVICE_TO_HOST |
                       USB_HAUDIO_REQ_CLASS      |
                       USB_HAUDIO_ENDPOINT         );
    Req_Table[ 1 ] = wValue;
    Req_Table[ 2 ] = wIndex;
    Req_Table[ 3 ] = size;

    ret = usb0_api_class_request( devadr, &Req_Table[ 0 ], buff );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        return ret;
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_stream_GetMax
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_GetMax(uint16_t devadr, uint16_t wValue, uint16_t wIndex,
                                      uint8_t *buff, uint16_t size                        )
{
    uint16_t    Req_Table[ 4 ];
    int32_t     ret;

    Req_Table[ 0 ] = ( USB_HAUDIO_GET_MAX        |
                       USB_HAUDIO_DEVICE_TO_HOST |
                       USB_HAUDIO_REQ_CLASS      |
                       USB_HAUDIO_ENDPOINT         );
    Req_Table[ 1 ] = wValue;
    Req_Table[ 2 ] = wIndex;
    Req_Table[ 3 ] = size;

    ret = usb0_api_class_request( devadr, &Req_Table[ 0 ], buff );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        return ret;
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: R_USB_api_haudio_stream_GetRes
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_GetRes(uint16_t devadr, uint16_t wValue, uint16_t wIndex,
                                      uint8_t *buff, uint16_t size                        )
{
    uint16_t    Req_Table[ 4 ];
    int32_t     ret;

    Req_Table[ 0 ] = ( USB_HAUDIO_GET_RES        |
                       USB_HAUDIO_DEVICE_TO_HOST |
                       USB_HAUDIO_REQ_CLASS      |
                       USB_HAUDIO_ENDPOINT         );
    Req_Table[ 1 ] = wValue;
    Req_Table[ 2 ] = wIndex;
    Req_Table[ 3 ] = size;

    ret = usb0_api_class_request( devadr, &Req_Table[ 0 ], buff );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        return ret;
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_stream_SetCur
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_SetCur(uint16_t devadr, uint16_t wValue, uint16_t wIndex,
                                      uint8_t *buff, uint16_t size                        )
{
    uint16_t    Req_Table[ 4 ];
    int32_t     ret;

    Req_Table[ 0 ] = ( USB_HAUDIO_SET_CUR        |
                       USB_HAUDIO_HOST_TO_DEVICE |
                       USB_HAUDIO_REQ_CLASS      |
                       USB_HAUDIO_ENDPOINT         );
    Req_Table[ 1 ] = wValue;
    Req_Table[ 2 ] = wIndex;
    Req_Table[ 3 ] = size;

    ret = usb0_api_class_request( devadr, &Req_Table[ 0 ], buff );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        return ret;
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_stream_SetMin
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_SetMin(uint16_t devadr, uint16_t wValue, uint16_t wIndex,
                                      uint8_t *buff, uint16_t size                        )
{
    uint16_t    Req_Table[ 4 ];
    int32_t     ret;

    Req_Table[ 0 ] = ( USB_HAUDIO_SET_MIN        |
                       USB_HAUDIO_HOST_TO_DEVICE |
                       USB_HAUDIO_REQ_CLASS      |
                       USB_HAUDIO_ENDPOINT         );
    Req_Table[ 1 ] = wValue;
    Req_Table[ 2 ] = wIndex;
    Req_Table[ 3 ] = size;

    ret = usb0_api_class_request( devadr, &Req_Table[ 0 ], buff );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        return ret;
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_stream_SetMax
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_SetMax(uint16_t devadr, uint16_t wValue, uint16_t wIndex,
                                      uint8_t *buff, uint16_t size                        )
{
    uint16_t    Req_Table[ 4 ];
    int32_t     ret;

    Req_Table[ 0 ] = ( USB_HAUDIO_SET_MAX        |
                       USB_HAUDIO_HOST_TO_DEVICE |
                       USB_HAUDIO_REQ_CLASS      |
                       USB_HAUDIO_ENDPOINT         );
    Req_Table[ 1 ] = wValue;
    Req_Table[ 2 ] = wIndex;
    Req_Table[ 3 ] = size;

    ret = usb0_api_class_request( devadr, &Req_Table[ 0 ], buff );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        return ret;
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_api_haudio_stream_SetRes
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
int32_t usb0_api_haudio_stream_SetRes(uint16_t devadr, uint16_t wValue, uint16_t wIndex,
                                      uint8_t *buff, uint16_t size                        )
{
    uint16_t    Req_Table[ 4 ];
    int32_t     ret;

    Req_Table[ 0 ] = ( USB_HAUDIO_SET_RES        |
                       USB_HAUDIO_HOST_TO_DEVICE |
                       USB_HAUDIO_REQ_CLASS      |
                       USB_HAUDIO_ENDPOINT         );
    Req_Table[ 1 ] = wValue;
    Req_Table[ 2 ] = wIndex;
    Req_Table[ 3 ] = size;

    ret = usb0_api_class_request( devadr, &Req_Table[ 0 ], buff );
    if( ret != USB_HAUDIO_SUCCESS )
    {
        return ret;
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_haudio_check_terminal
* Description  : Check Descriptor and return INPUT Terminal ID that linked
                 OUTPUT terminal ID of speakerto decide Interface.
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
static int32_t usb0_haudio_check_terminal(uint8_t *config_desc ,uint16_t desc_length, uint8_t* terminal_id)
{
    int32_t                    result               = USB_HAUDIO_ERROR;
    uint16_t                   offset               = 0;
    uint16_t                   work_terminal_type   = 0;
    uint8_t                    count_1              = 0;
    uint8_t                    count_2              = 0;
    uint8_t                    unit_info_num        = 0;
    uint8_t                    input_terminal_num   = 0;
    USB_AUD_UNIT_CONFIG_t      unit_info[USB_AUD_UNIT_INFO_SIZE];
    USB_AUD_TERMINAL_INFO_t    output_terminal_info;
    uint8_t                    input_terminal_id[USB_AUD_INPUT_TID_SIZE];
    uint8_t                    start                = 0;
    uint8_t                    end                  = 0;
    uint8_t                    search_buff[USB_AUD_SEARCH_BUFF_SIZE];
    uint8_t                    candidate_tid[USB_AUD_CANDIDATE_TID_SIZE];
    uint8_t                    candidate_tid_num    = 0;
    uint8_t                    over_lap             = 0;

    if ((config_desc != NULL) && (terminal_id != NULL))
    {
        /* Initialize RAM */
        /* Unit Info */
        for (count_1 = 0; count_1 < USB_AUD_UNIT_INFO_SIZE; count_1++)
        {
            unit_info[count_1].unit_id       = 0;
            unit_info[count_1].source_id_num = 0;
            for (count_2 = 0; count_2 < USB_AUD_UNIT_SRC_ID_SIZE; count_2++)
            {
                unit_info[count_1].source_id_table[count_2] = 0;
            }
        }
        /* INPUT Terminal Info */
        for (count_1 = 0; count_1 < USB_AUD_INPUT_TID_SIZE; count_1++)
        {
            input_terminal_id[count_1] = 0;
        }
        /* Serach ID(Unit or Terminal) Info */
        for (count_1 = 0; count_1 < USB_AUD_SEARCH_BUFF_SIZE; count_1++)
        {
            search_buff[count_1] = 0;
        }
        /* Candidate INPUT Terminal ID Info */
        for (count_1 = 0; count_1 < USB_AUD_CANDIDATE_TID_SIZE; count_1++)
        {
            candidate_tid[count_1] = 0;
        }
        /* OUTPUT Terminal Info */
        output_terminal_info.terminal_id = 0;
        output_terminal_info.source_id   = 0;

        /* Check descriptor info */
        while( offset < desc_length )
        {
            if( config_desc[ offset + 1 ] == USB_DT_CS_INTERFACE )
            {
                /* check descriptor sub type */
                switch( config_desc[ offset + 2 ] )
                {
                case USB_DST_INPUT_TERMINAL:
                    work_terminal_type = 0;
                    work_terminal_type = (((uint16_t)config_desc[ offset + 5 ] << 8) & 0xFF00);
                    work_terminal_type |= ((uint16_t)config_desc[ offset + 4 ] & 0x00FF);
                    if (work_terminal_type == USB_T_TYPE_USB_STREAM)
                    {
                        /* Terminal Type is USB streaming */
                        input_terminal_id[input_terminal_num] = config_desc[ offset + 3 ];
                        input_terminal_num++;
                    }
                    break;
                case USB_DST_OUTPUT_TERMINAL:
                    work_terminal_type = 0;
                    work_terminal_type = (((uint16_t)config_desc[ offset + 5 ] << 8) & 0xFF00);
                    work_terminal_type |= ((uint16_t)config_desc[ offset + 4 ] & 0x00FF);
                    if (work_terminal_type == USB_T_TYPE_SPEAKER)
                    {
                        /* Terminal Type is Speaker */
                        output_terminal_info.terminal_id = config_desc[ offset + 3 ];
                        output_terminal_info.source_id   = config_desc[ offset + 7 ];
                    }
                    break;
                case USB_DST_MIXER_UNIT:
                case USB_DST_SELECTOR_UNIT:
                    unit_info[unit_info_num].unit_id            = config_desc[ offset + 3 ];
                    unit_info[unit_info_num].source_id_num      = config_desc[ offset + 4 ];
                    for (count_1 = 0; count_1 < config_desc[ offset + 4 ]; count_1++ )
                    {
                        unit_info[unit_info_num].source_id_table[count_1] = config_desc[ offset + 5 + count_1 ];
                    }
                    unit_info_num++;
                    break;
                case USB_DST_FEATURE_UNIT:
                    unit_info[unit_info_num].unit_id            = config_desc[ offset + 3 ];
                    unit_info[unit_info_num].source_id_num      = 1;
                    unit_info[unit_info_num].source_id_table[0] = config_desc[ offset + 4 ];
                    unit_info_num++;
                    break;
                default:
                    break;
                }
            }

            if( config_desc[ offset ] == 0 )
            {
                break;
            }
            offset += config_desc[ offset ];
        }

        if (output_terminal_info.terminal_id != 0)
        {
            /* Found OUTPUT Terminal ID of speaker */
            start              = 0;      /* start point is top of search_buff */
            end                = 1;      /* source_id to be searched is only one at first */
            search_buff[start] = output_terminal_info.source_id;
            /* Search unit ID linked OUTPUT Terminal ID of speaker */
            while ( start != end )
            {
                count_1 = 0;
                /* Search unit ID */
                while (count_1 < unit_info_num)
                {
                    if (search_buff[start] == unit_info[count_1].unit_id)
                    {
                        /* Add source ID to search_buff and reflesh end point */
                        for (count_2 = 0; count_2 < unit_info[count_1].source_id_num; count_2++)
                        {
                            search_buff[end] = unit_info[count_1].source_id_table[count_2];
                            end++;
                            if (end >= USB_AUD_SEARCH_BUFF_SIZE)
                            {
                                end = 0;
                            }
                        }
                        break;
                    } else {
                        count_1++;
                    }
                }
                if (count_1 >= unit_info_num)
                {
                    /* There are no Unit ID. So search_buff[start] is INPUT Terminal ID */
                    /* check overlap */
                    over_lap = 0;
                    for (count_2 = 0; count_2 < candidate_tid_num; count_2++)
                    {
                        if (search_buff[start] == candidate_tid[count_2])
                        {
                            over_lap = 1;
                        }
                    }
                    if (over_lap == 0)
                    {
                        /* Non over lap. Store memory search_buff[start] as candidate INPUT Terminal ID */
                        candidate_tid[candidate_tid_num] = search_buff[start];
                        candidate_tid_num++;
                    }
                }
                if (start < (USB_AUD_SEARCH_BUFF_SIZE - 1))
                {
                    start++;
                } else {
                    start = 0;
                }
            }
            /* Check Input Terminal ID */
            count_1 = 0;
            while (count_1 < candidate_tid_num)
            {
                for (count_2 = 0; count_2 < input_terminal_num; count_2++)
                {
                    if (candidate_tid[count_1] == input_terminal_id[count_2])
                    {
                        *terminal_id = candidate_tid[count_1];
                        result = USB_HAUDIO_SUCCESS;
                    }
                }
                if (result != USB_HAUDIO_ERROR)
                {
                    break;
                }
            }
        }
    }
    return result;
}

/*******************************************************************************
* Function Name: usb0_haudio_check
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
static int32_t usb0_haudio_check(uint16_t devadr, uint8_t *ConfigDesctable, uint16_t set_config_flag )
{
    uint16_t    offset;
    int32_t     ret;
    uint16_t    TotalLength;
    uint16_t    InterfaceNum;
    uint16_t    AudioInterfaceNum;
    uint16_t    StreamInterfaceNum;
    uint8_t*    InterfaceDescTable;
    uint8_t     sample_num;
    uint32_t    sample_rate[USB_HAUDIO_MAX_SAMPLE_NUM];
    uint8_t     input_terminal_id;
    uint8_t     srcid;
    uint8_t     c_srcid;
    uint8_t     BitResolution;
    uint8_t     SubframeSize;


    /* Iniitalize Audio Class Informations */
    for( AudioInterfaceNum = 0; AudioInterfaceNum < USB_HAUDIO_MAX_INTERFACE; AudioInterfaceNum++ )
    {
        g_usb0_haudio[ devadr ].InterfaceType[ AudioInterfaceNum ].Type      = USB_HAUDIO_INVALID;
        g_usb0_haudio[ devadr ].InterfaceType[ AudioInterfaceNum ].Interface = USB_HAUDIO_INVALID;
        g_usb0_haudio[ devadr ].InterfaceType[ AudioInterfaceNum ].AltNum    = USB_HAUDIO_INVALID;
    }

    /* Initialize Audio Control Informations */
    g_usb0_haudio[ devadr ].Control.Interface   = USB_HAUDIO_INVALID;
    g_usb0_haudio[ devadr ].Control.OffAltNum   = USB_HAUDIO_INVALID;
    g_usb0_haudio[ devadr ].Control.OnAltNum    = USB_HAUDIO_INVALID;
    g_usb0_haudio[ devadr ].Control.PipeNum     = USB_HAUDIO_INVALID;
    g_usb0_haudio[ devadr ].AudioSrc.SrcId = 0;
    g_usb0_haudio[ devadr ].AudioSrc.ClockSrcId = 0;

    /* Initialize Audio Stream-IN Informations */
    g_usb0_haudio[ devadr ].StreamIn.Interface  = USB_HAUDIO_INVALID;
    g_usb0_haudio[ devadr ].StreamIn.OnAltNum   = USB_HAUDIO_INVALID;
    g_usb0_haudio[ devadr ].StreamIn.OffAltNum  = USB_HAUDIO_INVALID;
    g_usb0_haudio[ devadr ].StreamIn.PipeNum    = USB_HAUDIO_INVALID;
    g_usb0_haudio[ devadr ].StreamIn.Sample_Num = 0;

    /* Initialize Audio Stream-Out Informations */
    g_usb0_haudio[ devadr ].StreamOut.Interface  = USB_HAUDIO_INVALID;
    g_usb0_haudio[ devadr ].StreamOut.OnAltNum   = USB_HAUDIO_INVALID;
    g_usb0_haudio[ devadr ].StreamOut.OffAltNum  = USB_HAUDIO_INVALID;
    g_usb0_haudio[ devadr ].StreamOut.PipeNum    = USB_HAUDIO_INVALID;
    g_usb0_haudio[ devadr ].StreamOut.Sample_Num = 0;
    g_usb0_haudio[ devadr ].StreamOut.BitResolution = 0;

    if( set_config_flag == USB_HAUDIO_YES )
    {
        ret = usb0_api_class_SetConfiguration( devadr, (uint8_t)ConfigDesctable[ 5 ] );
        if(ret != USB_SUCCESS)
        {
            return ret;
        }
    }

    g_usb0_haudio[ devadr ].InterfaceNum = ConfigDesctable[ 4 ];        /* the count of interface */

    AudioInterfaceNum  = 0;            /* Count up of Interface num */
    StreamInterfaceNum = 0;            /* Count up of Stream Interface num */

    offset      = 0;
    TotalLength = (uint16_t)( ConfigDesctable[ 2 ] + ((uint16_t)ConfigDesctable[ 3 ] << 8) );

    usb0_api_hcd_clear_eptype( (USB_HOST_CFG_PIPETBL_t *)g_usb0_haudio[ devadr ].audio_regist->pipe_table);

    ret = usb0_haudio_check_terminal( ConfigDesctable, TotalLength, &input_terminal_id);
    if(ret != USB_HAUDIO_SUCCESS)
    {
        return USB_HAUDIO_TYPE_ERROR;
    }
    /* search configuration descriptor */
    while( offset < TotalLength )
    {
        if( ConfigDesctable[ offset + 1 ] == USB_DT_INTERFACE )
        {
            if( ConfigDesctable[ offset + 5 ] == USB_IF_CLS_AUDIO )
            {
                /* check sub class */
                switch( ConfigDesctable[ offset + 6 ] )
                {
                case USB_HAUDIO_IF_SUB_CLS_AUDIO_CONTROL:
                    g_usb0_haudio[ devadr ].InterfaceType[ AudioInterfaceNum ].Interface = ConfigDesctable[ offset + 2 ];
                    g_usb0_haudio[ devadr ].InterfaceType[ AudioInterfaceNum ].AltNum    = ConfigDesctable[ offset + 3 ];
                    g_usb0_haudio[ devadr ].InterfaceType[ AudioInterfaceNum ].Type = USB_HAUDIO_CONTROL;

                    g_usb0_haudio[ devadr ].Control.Interface = ConfigDesctable[ offset + 2 ];
                    g_usb0_haudio[ devadr ].Control.OffAltNum = ConfigDesctable[ offset + 3 ];
                    g_usb0_haudio[ devadr ].Control.OnAltNum  = ConfigDesctable[ offset + 3 ];
                    g_usb0_haudio[ devadr ].Control.PipeNum   = USB_PIPE0;

                    if( ConfigDesctable[ offset + 4 ] != 0 ){
                        InterfaceDescTable = (uint8_t*)&ConfigDesctable[ offset ];
                        usb0_haudio_CheckAudioCtrl_Desc( InterfaceDescTable, &srcid, &c_srcid);
                        g_usb0_haudio[ devadr ].AudioSrc.SrcId = srcid;
                        g_usb0_haudio[ devadr ].AudioSrc.ClockSrcId = c_srcid;
                    }

                    AudioInterfaceNum++;
                    break;

                case USB_HAUDIO_IF_SUB_CLS_AUDIO_STREAM:
                    g_usb0_haudio[ devadr ].InterfaceType[ AudioInterfaceNum ].Interface = ConfigDesctable[ offset + 2 ];
                    g_usb0_haudio[ devadr ].InterfaceType[ AudioInterfaceNum ].AltNum    = ConfigDesctable[ offset + 3 ];

                    if( ConfigDesctable[ offset + 4 ] == 0 ){
                        /* no endpoint */
                        g_usb0_haudio[ devadr ].InterfaceType[ AudioInterfaceNum ].Type = USB_HAUDIO_STREAM_WO_EP;
                    }
                    else{
                        /* exist endpoint */
                        g_usb0_haudio[ devadr ].InterfaceType[ AudioInterfaceNum ].Type = USB_HAUDIO_STREAM_WI_EP;

                        InterfaceDescTable = (uint8_t*)&ConfigDesctable[ offset ];
                        if(ConfigDesctable[ offset + 7 ] == 0x00)
                        {
                            ret = usb0_haudio_CheckInterface( InterfaceDescTable, &sample_num,
                                                              &sample_rate[ 0 ], &BitResolution, &SubframeSize);
                        }
                        else
                        {
                            ret = usb0_haudio_CheckInterface_2( InterfaceDescTable, &sample_num,
                                                                &sample_rate[ 0 ], &BitResolution, &SubframeSize);
                        }

                        if( ret == USB_HAUDIO_SUCCESS )
                        {
                            if((g_usb0_haudio[ devadr ].StreamOut.BitResolution != 0)
                                && (g_usb0_haudio[ devadr ].StreamOut.BitResolution < BitResolution))
                            {
                                StreamInterfaceNum = 0;
                                g_usb0_haudio[ devadr ].StreamOut.Interface = USB_HAUDIO_INVALID;
                            }
                            ret = usb0_hauido_PipeInfo( devadr,
                                                       StreamInterfaceNum,
                                                       InterfaceDescTable,
                                                       TotalLength,
                                                       sample_num,
                                                       &sample_rate[ 0 ],
                                                       input_terminal_id,
                                                       BitResolution,
                                                       SubframeSize
                                                       );
                            if( ret == USB_HAUDIO_SUCCESS )
                            {
                                StreamInterfaceNum++;
                            }
                            else if( ret == USB_HAUDIO_SUCCESS2 )
                            {
                                /* nothing to do */
                            }
                            else
                            {
                                return USB_HAUDIO_TYPE_ERROR;
                            }
                        }
                    }

                    AudioInterfaceNum++;
                    break;
                }
            }
        }

        if( ConfigDesctable[ offset ] == 0 )
        {
            break;
        }

        offset += ConfigDesctable[ offset ];
    }

    if( AudioInterfaceNum == 0 ){
        /* Cant find Audio Interface */
        return USB_HAUDIO_TYPE_ERROR;
    }

    /* Search OffAltNum */
    InterfaceNum = 0;
    for( offset = 0; offset < AudioInterfaceNum; offset++ )
    {
        if( g_usb0_haudio[ devadr ].InterfaceType[ offset ].Type == USB_HAUDIO_STREAM_WO_EP )
        {
            /* No Endpoint Interface */
            if( g_usb0_haudio[ devadr ].InterfaceType[ offset ].Interface == g_usb0_haudio[ devadr ].StreamIn.Interface )
            {
                /* Stream-IN Interface */
                g_usb0_haudio[ devadr ].StreamIn.OffAltNum = g_usb0_haudio[ devadr ].InterfaceType[ offset ].AltNum;

                InterfaceNum++;
            }
            else if( g_usb0_haudio[ devadr ].InterfaceType[ offset ].Interface == g_usb0_haudio[ devadr ].StreamOut.Interface )
            {
                /* Stream-OUT Interface */
                g_usb0_haudio[ devadr ].StreamOut.OffAltNum = g_usb0_haudio[ devadr ].InterfaceType[ offset ].AltNum;

                InterfaceNum++;
            }

            if( InterfaceNum == StreamInterfaceNum )
            {
                break;
            }
        }
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_haudio_CheckInterface
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
static int32_t usb0_haudio_CheckInterface( uint8_t *InterfaceDescTable, uint8_t *sample_num, uint32_t *sample_rate,
                                            uint8_t *BitResolution, uint8_t *SubframeSize)
{
    uint8_t     loop;
    uint8_t     *AsGenerealDescTable;
    uint16_t    formta_tag;
    uint8_t     *FormatTypeDescTable;
    uint16_t    ofst;

    /* ==== check AS_GENERAL Descriptor ==== */
    AsGenerealDescTable = (uint8_t *)( &InterfaceDescTable[ InterfaceDescTable[ 0 ] ] );
    if( (AsGenerealDescTable[ 1 ] != USB_HAUDIO_IF_CS_INTERFACE ) ||
        (AsGenerealDescTable[ 2 ] != USB_HAUDIO_IF_CS_AS_GENERAL)     )
    {
        return USB_HAUDIO_TYPE_ERROR;
    }

    /* check wFormatTag */
    formta_tag = (uint16_t)( AsGenerealDescTable[ 5 ] + ((uint16_t)AsGenerealDescTable[ 6 ] << 8) );
    if( formta_tag != USB_HAUDIO_PCM )
    {
        /* not PCM */
        return USB_HAUDIO_TYPE_ERROR;
    }

    /* ==== check FORMAT TYPE Descriptor ==== */
    FormatTypeDescTable = (uint8_t *)( &AsGenerealDescTable[ AsGenerealDescTable[0] ] );
    if( (FormatTypeDescTable[ 1 ] != USB_HAUDIO_IF_CS_INTERFACE  ) ||
        (FormatTypeDescTable[ 2 ] != USB_HAUDIO_IF_CS_FORMAT_TYPE)     )
    {
        return USB_HAUDIO_TYPE_ERROR;
    }

    /* check bNrChannels */
    if( FormatTypeDescTable[ 4 ] != 2 )
    {
        return USB_HAUDIO_TYPE_ERROR;
    }

    /* check bSubframeSize */
    if(( FormatTypeDescTable[ 5 ] != 2 ) && ( FormatTypeDescTable[ 5 ] != 3 ))
    {
        return USB_HAUDIO_TYPE_ERROR;
    }

    /* check bBitResolution */
    if(( FormatTypeDescTable[ 6 ] != 16 ) && ( FormatTypeDescTable[ 6 ] != 24 ))
    {
        return USB_HAUDIO_TYPE_ERROR;
    }

    /* check tSamFreq */
    if( FormatTypeDescTable[ 7 ] > USB_HAUDIO_MAX_SAMPLE_NUM )
    {
        return USB_HAUDIO_TYPE_ERROR;
    }
    *BitResolution = FormatTypeDescTable[ 6 ];
    *SubframeSize = FormatTypeDescTable[ 5 ];
    *sample_num = FormatTypeDescTable[ 7 ];
    ofst = 8;
    for( loop = 0; loop < FormatTypeDescTable[ 7 ]; loop++ )
    {
        sample_rate[ loop ] = (uint32_t)( FormatTypeDescTable[ ofst ] +
                                          ((uint32_t)FormatTypeDescTable[ ofst + 1 ] <<  8) +
                                          ((uint32_t)FormatTypeDescTable[ ofst + 2 ] << 16)   );
        ofst += 3;
    }

    return USB_HAUDIO_SUCCESS;
}

/*******************************************************************************
* Function Name: usb0_haudio_CheckInterface_2
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
static int32_t usb0_haudio_CheckInterface_2( uint8_t *InterfaceDescTable, uint8_t *sample_num, uint32_t *sample_rate,
                                            uint8_t *BitResolution, uint8_t *SubframeSize)
{
    uint8_t     loop;
    uint8_t     *AsGenerealDescTable;
    uint16_t    formta_tag;
    uint8_t     *FormatTypeDescTable;
    uint16_t    ofst;

    /* ==== check AS_GENERAL Descriptor ==== */
    AsGenerealDescTable = (uint8_t *)( &InterfaceDescTable[ InterfaceDescTable[ 0 ] ] );
    if((AsGenerealDescTable[ 1 ] != USB_HAUDIO_IF_CS_INTERFACE ) ||
        (AsGenerealDescTable[ 2 ] != USB_HAUDIO_IF_CS_AS_GENERAL))
    {
        return USB_HAUDIO_TYPE_ERROR;
    }
    /* check bNrChannels */
    if( AsGenerealDescTable[ 10 ] != 2 )
    {
        return USB_HAUDIO_TYPE_ERROR;
    }

    /* ==== check FORMAT TYPE Descriptor ==== */
    FormatTypeDescTable = (uint8_t *)( &AsGenerealDescTable[ AsGenerealDescTable[0] ] );
    if( (FormatTypeDescTable[ 1 ] != USB_HAUDIO_IF_CS_INTERFACE  ) ||
        (FormatTypeDescTable[ 2 ] != USB_HAUDIO_IF_CS_FORMAT_TYPE)     )
    {
        return USB_HAUDIO_TYPE_ERROR;
    }

    /* check bSubframeSize */
    if(( FormatTypeDescTable[ 4 ] != 2 ) && ( FormatTypeDescTable[ 4 ] != 4 ))
    {
        return USB_HAUDIO_TYPE_ERROR;
    }

    /* check bBitResolution */
    if(( FormatTypeDescTable[ 5 ] != 16 ) && ( FormatTypeDescTable[ 5 ] != 24 ))
    {
        return USB_HAUDIO_TYPE_ERROR;
    }

    *BitResolution = FormatTypeDescTable[ 5 ];
    *SubframeSize = FormatTypeDescTable[ 4 ];
    *sample_num = 0;

    return USB_HAUDIO_SUCCESS;
}


/*******************************************************************************
* Function Name: usb0_haudio_CheckAudioCtrl_Desc
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
static int32_t usb0_haudio_CheckAudioCtrl_Desc( uint8_t *InterfaceDescTable, uint8_t *SrcId, uint8_t *C_SrcId)
{
    uint8_t     loop;
    uint8_t     *AcDescTable;
    uint16_t    ofst;
    uint16_t    total_length;
    uint32_t    offset;
    uint16_t    term_type;

    /* ==== check AS_GENERAL Descriptor ==== */
    AcDescTable = (uint8_t *)( &InterfaceDescTable[ InterfaceDescTable[ 0 ] ] );

    if((AcDescTable[ 1 ] != USB_HAUDIO_IF_CS_INTERFACE ) ||
        (AcDescTable[ 2 ] != USB_HAUDIO_IF_HEADER))
    {
        return USB_HAUDIO_TYPE_ERROR;
    }
    *SrcId = 0;
    *C_SrcId = 0;
    offset = 0;
    total_length = (uint16_t)(AcDescTable[6] + (AcDescTable[ 7 ] << 8));

    while(offset < total_length)
    {
        if((AcDescTable[ offset + 1 ] == USB_HAUDIO_IF_CS_INTERFACE ) &&
            (AcDescTable[ offset + 2 ] == USB_HAUDIO_IF_OUTPUT_TERMINAL))
        {
            term_type = (uint16_t)(AcDescTable[offset + 4] + (AcDescTable[offset + 5] << 8));
            if(term_type == 0x0301)
            {
                *SrcId = AcDescTable[ offset + 7 ];
                *C_SrcId = AcDescTable[ offset + 8 ];
                return USB_HAUDIO_SUCCESS;
            }
        }
        offset += AcDescTable[ offset ];
    }
    return USB_HAUDIO_SUCCESS;
}


/*******************************************************************************
* Function Name: usb0_hauido_PipeInfo
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
static int32_t usb0_hauido_PipeInfo( uint16_t devadr, uint16_t index,
                                     uint8_t *Table, uint16_t TotalLength,
                                     uint8_t sample_num, uint32_t *sample_rate,
                                     uint8_t speaker_terminal_id,
                                     uint8_t BitResolution, uint8_t SubframeSize)
{
    uint8_t                   loop;
    int32_t                   ret;
    uint16_t                  ofset;
    uint16_t                  retval;
    uint16_t                  audioend_cnt;
    USB_HOST_CFG_PIPETBL_t    *ptr;
    uint16_t                  iitv;
    uint8_t     *AsGenerealDescTable;
    AsGenerealDescTable = (uint8_t *)( &Table[ Table[ 0 ] ] );

    ptr = (USB_HOST_CFG_PIPETBL_t *)g_usb0_haudio[ devadr ].audio_regist->pipe_table;
    while( index )
    {
        ptr++;
        if( ptr->pipe_number == USB_PIPE_TBL_END )
        {
            /* pipe table over */
            if( (g_usb0_haudio[ devadr ].StreamIn.Interface  == USB_HAUDIO_INVALID) ||
                (g_usb0_haudio[ devadr ].StreamOut.Interface == USB_HAUDIO_INVALID)    )
            {
                /* not find StreamIn or StreamOut */
                return USB_HAUDIO_ERROR;
            }
            return USB_HAUDIO_SUCCESS2;
        }
        index--;
    }

    ret   = USB_HAUDIO_SUCCESS;
    ofset = Table[ 0 ];
    audioend_cnt = 0;
    do
    {
        if( Table[ ofset + 1 ] == USB_DT_ENDPOINT )
        {
            if( (Table[ ofset + 3 ] & USB_EP_TRNS_MASK) == USB_EP_ISO )
            {
                /* ISO Endpoint */
                retval = usb0_api_hcd_set_pipe_info( devadr, ptr, (uint8_t *)&Table[ ofset ]);
                if(retval == USB_PIPE_IN)
                {
                    /* ISO-IN Endpoint */
                    if( g_usb0_haudio[ devadr ].StreamIn.Interface != USB_HAUDIO_INVALID )
                    {
                        /* Already set */
                        audioend_cnt++;
                        ret = USB_HAUDIO_SUCCESS2;
                        break;
                    }

                    iitv = (ptr->pipe_cycle & USB_HAUDIO_IITV);
                    if( g_usb0_haudio[ devadr ].audio_dev_status == USB_HAUDIO_DEV_HIGH_ATT )
                    {
                        /* High-Speed */
                        if( iitv == 0 )
                        {
                            /* set to 1Frame */
                            iitv  = (ptr->pipe_cycle & ~USB_HAUDIO_IITV);
                            iitv |= 0x0003;
                            ptr->pipe_cycle = iitv;
                        }
                        else if( iitv == 3 )
                        {
                            /* nothing to do */
                        }
                        else
                        {
                            /* Not 1uFrame or 1Frame */
                            return USB_HAUDIO_ERROR;
                        }
                    }
                    else if( g_usb0_haudio[ devadr ].audio_dev_status == USB_HAUDIO_DEV_FULL_ATT )
                    {
                        /* Full-Speed */
                        if( iitv != 0 )
                        {
                            /* Not 1Frame */
                            return USB_HAUDIO_ERROR;
                        }
                    }
                    else
                    {
                        return USB_HAUDIO_ERROR;
                    }

                    if( ptr->fifo_port == USB_D1DMA )
                    {
                        ptr->fifo_port = USB_D0DMA;
                    }
                    g_usb0_haudio[ devadr ].StreamIn.Interface = Table[ 0 + 2 ];
                    g_usb0_haudio[ devadr ].StreamIn.OnAltNum  = Table[ 0 + 3 ];
                    g_usb0_haudio[ devadr ].StreamIn.PipeNum   = ptr->pipe_number;
                    g_usb0_haudio[ devadr ].StreamIn.FifoPort  = ptr->fifo_port;
                    g_usb0_haudio[ devadr ].StreamIn.EndPointAddress = Table[ ofset + 2 ];
                    g_usb0_haudio[ devadr ].StreamIn.MaxPacketSize = (uint16_t)(ptr->pipe_max_pktsize & USB_HAUDIO_PIPE_MAXPFIELD);
                    g_usb0_haudio[ devadr ].StreamIn.Sample_Num = sample_num;
                    for( loop = 0; loop < sample_num; loop++ )
                    {
                        g_usb0_haudio[ devadr ].StreamIn.Sample_Rate[ loop ] = sample_rate[ loop ];
                    }
                    audioend_cnt++;
                    ret = USB_HAUDIO_SUCCESS;
                    break;
                }
                else if((retval == USB_PIPE_OUT) && (AsGenerealDescTable[ 3 ] == speaker_terminal_id))
                {
                    /* ISO-OUT Endpoint */
                    if( g_usb0_haudio[ devadr ].StreamOut.Interface != USB_HAUDIO_INVALID )
                    {
                        /* Already set */
                        audioend_cnt++;
                        ret = USB_HAUDIO_SUCCESS2;
                        break;
                    }

                    iitv = (ptr->pipe_cycle & USB_HAUDIO_IITV);
                    if( g_usb0_haudio[ devadr ].audio_dev_status == USB_HAUDIO_DEV_HIGH_ATT )
                    {
                        /* High-Speed */
                        if( iitv == 0 )
                        {
                            /* nothing to do */
                        }
                        else if( iitv == 3 )
                        {
                            /* nothing to do */
                        }
                        else
                        {
                            /* Not 1uFrame or 1Frame */
                            return USB_HAUDIO_ERROR;
                        }
                    }
                    else if( g_usb0_haudio[ devadr ].audio_dev_status == USB_HAUDIO_DEV_FULL_ATT )
                    {
                        /* Full-Speed */
                        if( iitv != 0 )
                        {
                            /* Not 1Frame */
                            return USB_HAUDIO_ERROR;
                        }
                    }
                    else
                    {
                        return USB_HAUDIO_ERROR;
                    }

                    if( ptr->fifo_port == USB_D0DMA )
                    {
                        ptr->fifo_port = USB_D1DMA;
                    }
                        g_usb0_haudio[ devadr ].StreamOut.Interface = Table[ 0 + 2 ];
                        g_usb0_haudio[ devadr ].StreamOut.OnAltNum  = Table[ 0 + 3 ];
                        g_usb0_haudio[ devadr ].StreamOut.PipeNum   = ptr->pipe_number;
                        g_usb0_haudio[ devadr ].StreamOut.FifoPort  = ptr->fifo_port;
                        g_usb0_haudio[ devadr ].StreamOut.EndPointAddress = Table[ ofset + 2 ];
                        g_usb0_haudio[ devadr ].StreamOut.MaxPacketSize
                          = (uint16_t)(ptr->pipe_max_pktsize & USB_HAUDIO_PIPE_MAXPFIELD);
                        g_usb0_haudio[ devadr ].StreamOut.BitResolution = BitResolution;
                        g_usb0_haudio[ devadr ].StreamOut.SubframeSize = SubframeSize;
                        g_usb0_haudio[ devadr ].StreamOut.Sample_Num = sample_num;
                        for( loop = 0; loop < sample_num; loop++ )
                        {
                            g_usb0_haudio[ devadr ].StreamOut.Sample_Rate[ loop ] = sample_rate[ loop ];
                        }

                    audioend_cnt++;
                    ret = USB_HAUDIO_SUCCESS;
                    break;
                }
            }
        }

        if( Table[ ofset ] == 0 )
        {
            break;
        }

        /* Search Next Endpoint */
        ofset += Table[ ofset ];

    } while( ofset < TotalLength );

    if( audioend_cnt == 0)
    {
        /* Cannot find iso endpoint */
        return USB_HAUDIO_ERROR;
    }

    /* USB_HAUDIO_SUCCESS or USB_HAUDIO_SUCCESS2 */
    return ret;
}

/*******************************************************************************
* Function Name: usb0_haudio_SetDevSts
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
static void usb0_haudio_SetDevSts(uint16_t devadr, uint16_t speed)
{
    if( speed == USB_FSCONNECT )
    {
        g_usb0_haudio[ devadr ].audio_dev_status = USB_HAUDIO_DEV_FULL_ATT;
    }
    else if( speed == USB_HSCONNECT )
    {
        g_usb0_haudio[ devadr ].audio_dev_status = USB_HAUDIO_DEV_HIGH_ATT;
    }
    else
    {
        g_usb0_haudio[ devadr ].audio_dev_status = USB_HAUDIO_DEV_DET;
    }
}

/*******************************************************************************
* Function Name: usb0_haudio_SetDevDetachSts
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
static void usb0_haudio_SetDevDetachSts(uint16_t devadr)
{
    g_usb0_haudio[ devadr ].audio_dev_status = USB_HAUDIO_DEV_DET;
}

/*******************************************************************************
* Function Name: usb_haudio_GetDevSts
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
static int32_t usb0_haudio_GetDevSts(uint16_t devadr)
{
    if( (devadr > 0) && (devadr <= USB_HAUDIO_MAX_DEVADDRESS) )
    {
        return g_usb0_haudio[ devadr ].audio_dev_status;
    }

    return USB_HAUDIO_DEV_DET;
}




/*******************************************************************************
* Function Name: usb0_haudio_in_wait
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
static int32_t usb0_haudio_in_wait( uint16_t devadr, uint32_t timeout )
{
    int32_t                  err;
    USB_HCD_REQUEST_ISO_t    *msg;

    if( timeout == 0 )
    {
        err = usb0_userdef_os_rcv_mbx( USB_HAUDIO_IN, (void **)&msg );
        if ( err != USB_HAUDIO_SUCCESS )
        {
            return USB_HAUDIO_ERROR;
        }
    }
    else
    {
        err = usb0_userdef_os_trcv_mbx( USB_HAUDIO_IN, (void **)&msg, timeout );
        if( err == USB_HAUDIO_TIMEOUT )
        {
            return USB_HAUDIO_NAK_TIMEOUT;
        }
        else if( err != USB_HAUDIO_SUCCESS )
        {
            return USB_HAUDIO_ERROR;
        }
    }

    return msg->status;
}

/*******************************************************************************
* Function Name: usb0_haudio_in_hcd_request_result
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
static int32_t usb0_haudio_in_hcd_request_result( USB_HCD_REQUEST_ISO_t *usb_hcd_request_iso_msg )
{
    int32_t      err;
    uint16_t     devadr;
    void         *ptr;

    if( usb_hcd_request_iso_msg->status == USB_HCD_DATA_OK )
    {
        devadr = usb_hcd_request_iso_msg->devadr;
        g_usb0_haudio[ devadr ].StreamIn.CurrentSize  = usb_hcd_request_iso_msg->transfer_length;
        g_usb0_haudio[ devadr ].StreamIn.CurrentBuff  = g_usb0_haudio[ devadr ].StreamIn.ReloadBuff;
        g_usb0_haudio[ devadr ].StreamIn.CurrentCount = g_usb0_haudio[ devadr ].StreamIn.ReloadCount;
        g_usb0_haudio[ devadr ].StreamIn.TransSize    = g_usb0_haudio[ devadr ].StreamIn.ReloadTransSize;

        err = usb0_api_hcd_request_reload( devadr,
                                           g_usb0_haudio[ devadr ].StreamIn.PipeNum,
                                           g_usb0_haudio[ devadr ].StreamIn.ReloadTransSize,
                                           g_usb0_haudio[ devadr ].StreamIn.ReloadBuff );
    }

    usb_hcd_request_iso_msg->msg_header = USB_HCD_REQUEST_MESSAGE;
    ptr = (void *)usb_hcd_request_iso_msg;
    err = usb0_userdef_os_snd_mbx( USB_HAUDIO_IN, (void *)ptr );

    return err;
}

/*******************************************************************************
* Function Name: usb0_haudio_out_wait
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
static int32_t usb0_haudio_out_wait( uint16_t devadr, uint32_t timeout )
{
    int32_t                  err;
    USB_HCD_REQUEST_ISO_t    *msg;

    if( timeout == 0 )
    {
        err = usb0_userdef_os_rcv_mbx( USB_HAUDIO_OUT, (void **)&msg );
        if ( err != USB_HAUDIO_SUCCESS )
        {
            return USB_HAUDIO_ERROR;
        }
    }
    else
    {
        err = usb0_userdef_os_trcv_mbx( USB_HAUDIO_OUT, (void **)&msg, timeout );
        if( err == USB_HAUDIO_TIMEOUT )
        {
            return USB_HAUDIO_NAK_TIMEOUT;
        }
        else if( err != USB_HAUDIO_SUCCESS )
        {
            return USB_HAUDIO_ERROR;
        }
    }

    return msg->status;
}

/*******************************************************************************
* Function Name: usb0_haudio_out_hcd_request_result
* Description  :
* Outline      :
* Argument     :
* Return Value :
*******************************************************************************/
static int32_t usb0_haudio_out_hcd_request_result( USB_HCD_REQUEST_ISO_t *usb_hcd_request_iso_msg )
{
    int32_t      err;
    uint16_t     devadr;
    void         *ptr;

    devadr = usb_hcd_request_iso_msg->devadr;

    usb_hcd_request_iso_msg->msg_header = USB_HCD_REQUEST_MESSAGE;
    ptr = (void *)usb_hcd_request_iso_msg;
    err = usb0_userdef_os_snd_mbx( USB_HAUDIO_OUT, (void *)ptr );

    return err;
}


/* End of File */
