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

 * @fn      USB2HostTransact

 *

 * @brief   传输事务,输入目的端点地址/PID令牌,同步标志,以20uS为单位的NAK重试总时间(0则不重试,0xFFFF无限重试),返回0成功,超时/出错重试

 *          本子程序着重于易理解,而在实际应用中,为了提供运行速度,应该对本子程序代码进行优化

 *

 * @param   endp_pid    - 令牌和地址, 高4位是token_pid令牌, 低4位是端点地址

 * @param   tog         - 同步标志

 * @param   timeout     - 超时时间

 *

 * @return  ERR_USB_UNKNOWN 超时,可能硬件异常

 *          ERR_USB_DISCON  设备断开

 *          ERR_USB_CONNECT 设备连接

 *          ERR_SUCCESS     传输完成

 */

uint8_t USB2HostTransact(uint8_t endp_pid, uint8_t tog, uint32_t timeout)

{

    uint8_t TransRetry;


    uint8_t  s, r;

    uint16_t i;


    R8_U2H_RX_CTRL = R8_U2H_TX_CTRL = tog;

    TransRetry = 0;


    do

    {

        R8_U2H_EP_PID = endp_pid; // 指定令牌PID和目的端点号

        R8_USB2_INT_FG = RB_UIF_TRANSFER;

        for(i = WAIT_USB_TOUT_200US; i != 0 && (R8_USB2_INT_FG & RB_UIF_TRANSFER) == 0; i--)

            ;

        R8_U2H_EP_PID = 0x00; // 停止USB传输

        if((R8_USB2_INT_FG & RB_UIF_TRANSFER) == 0)

        {

            return (ERR_USB_UNKNOWN);

        }


        if(R8_USB2_INT_FG & RB_UIF_DETECT)

        { // USB设备插拔事件

            //      mDelayuS( 200 );                                                       // 等待传输完成

            R8_USB2_INT_FG = RB_UIF_DETECT;

            s = AnalyzeRootU2Hub(); // 分析ROOT-U2HUB状态


            if(s == ERR_USB_CONNECT)

                FoundNewU2Dev = 1;

#ifdef DISK_BASE_BUF_LEN

            if(CHRV3DiskStatus == DISK_DISCONNECT)

            {

                return (ERR_USB_DISCON);

            } // USB设备断开事件

            if(CHRV3DiskStatus == DISK_CONNECT)

            {

                return (ERR_USB_CONNECT);

            } // USB设备连接事件

#else

            if(ThisUsb2Dev.DeviceStatus == ROOT_DEV_DISCONNECT)

            {

                return (ERR_USB_DISCON);

            } // USB设备断开事件

            if(ThisUsb2Dev.DeviceStatus == ROOT_DEV_CONNECTED)

            {

                return (ERR_USB_CONNECT);

            } // USB设备连接事件

#endif

            mDelayuS(200); // 等待传输完成

        }


        if(R8_USB2_INT_FG & RB_UIF_TRANSFER) // 传输完成事件

        {

            if(R8_USB2_INT_ST & RB_UIS_TOG_OK)

            {

                return (ERR_SUCCESS);

            }

            r = R8_USB2_INT_ST & MASK_UIS_H_RES; // USB设备应答状态

            if(r == USB_PID_STALL)

            {

                return (r | ERR_USB_TRANSFER);

            }

            if(r == USB_PID_NAK)

            {

                if(timeout == 0)

                {

                    return (r | ERR_USB_TRANSFER);

                }

                if(timeout < 0xFFFFFFFF)

                    timeout--;

                --TransRetry;

            }

            else

                switch(endp_pid >> 4)

                {

                    case USB_PID_SETUP:

                    case USB_PID_OUT:

                        if(r)

                        {

                            return (r | ERR_USB_TRANSFER);

                        }      // 不是超时/出错,意外应答

                        break; // 超时重试

                    case USB_PID_IN:

                        if(r == USB_PID_DATA0 || r == USB_PID_DATA1)

                        { // 不同步则需丢弃后重试

                        } // 不同步重试

                        else if(r)

                        {

                            return (r | ERR_USB_TRANSFER);

                        }      // 不是超时/出错,意外应答

                        break; // 超时重试

                    default:

                        return (ERR_USB_UNKNOWN); // 不可能的情况

                        break;

                }

        }

        else

        {                          // 其它中断,不应该发生的情况

            R8_USB2_INT_FG = 0xFF; /* 清中断标志 */

        }

        mDelayuS(15);

    } while(++TransRetry < 3);

    return (ERR_USB_TRANSFER); // 应答超时

}