⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbtransfer.c

📁 smartARM2400 USB OTG例程
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************Copyright(c)****************************************************************
**                    Guangzhou ZHIYUAN electronics Co.,LTD.
**                                     
**                           http://www.embedtools.com
**
**------File Info-----------------------------------------------------------------------------------------
** File Name:            USBTransfer.c
** Latest modified Date: 2007-11-14        
** Latest Version:       V1.0    
** Description:          USB主机软件包的传输函数
**                       
**--------------------------------------------------------------------------------------------------------
** Created By:           吴隆穗   Longsui Wu   
** Created date:         2007-11-14    
** Version:              V1.0    
** Descriptions:         初始版本
**
**--------------------------------------------------------------------------------------------------------
** Modified by:          
** Modified date:        
** Version:              
** Description:          
**
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Description:
**
*********************************************************************************************************/
#include "USBHostConfig.h"

USB_INT8U __usbCtrlTranPhase_Setup (PUSB_DEV_REQ pusbDevReq);
USB_INT8U __usbCtrlTranPhase_In (USB_INT16U usLength, USB_INT8U *pucBuf);
USB_INT8U __usbCtrlTranPhase_Out (void);

#ifdef __cplusplus
extern "C" {
#endif

/*********************************************************************************************************
** Function name:       usbStandardReqTransfer
** Descriptions:        发送标准请求, 并取得返回值
** input parameters:    pusbDevReq  标准请求
** output parameters:   pucBuf      设备返回的数据
**                      puiSts      状态,如错误号等
** Returned value:      错误码
*********************************************************************************************************/
USB_INT8U usbStandardReqTransfer (PUSB_DEV_REQ pusbDevReq, USB_INT8U *pucBuf)
{
    USB_INT8U ucErr, ucRet;

    if (GusbHostFlags.ucAttached == 0) {                                /*  设备未插入                  */
        return USB_ERR_DEVICE_NOT_ATTACHED;
    }
    
    OS_ENTER_CRITICAL();
    if (GusbHostFlags.bExitStdOperaReq) {                               /*  应用程序要求退出操作        */
        OS_EXIT_CRITICAL();
        return USB_ERR_EXIT_REQ;
    }
    __GusbHostEvtCnt.ucStdTranCnt++;                                    /*  控制传输计数器自加1			*/
    OS_EXIT_CRITICAL();
    
    OSSemPend(__GevtUsbCtrlSem, 0, &ucErr);
    
    do {                                                                /*  避免 goto 而使用 do...while */
        
        /*
         *  第一步: SETUP 阶段
         */
        ucRet = __usbCtrlTranPhase_Setup(pusbDevReq);
        if (ucRet != USB_ERR_SUCESS) {
            break;
        }
        
        /*
         *  第二步: IN 阶段
         */
        ucRet = __usbCtrlTranPhase_In (pusbDevReq->wLength, pucBuf);
        if (ucRet != USB_ERR_SUCESS) {
            break;
        }

        /*
         *  第三步: OUT 阶段, 只有 IN 阶段有数据传输时才需要此 OUT 阶段
         */
        if (pusbDevReq->wLength) {
            __usbCtrlTranPhase_Out();
        }
    } while (0);    
    
    OSSemPost(__GevtUsbCtrlSem);

    OS_ENTER_CRITICAL();
    __GusbHostEvtCnt.ucStdTranCnt--;                                    /*  控制传输计数器自减1			*/
    OS_EXIT_CRITICAL();
    
    return ucRet;
}

/*********************************************************************************************************
** Function name:       usbDataTransfer
** Descriptions:        发送或接收 Bulk, Intrrupt 传输的数据
** input parameters:    pucData       要发送或接收的数据缓冲区
**                      uiLength      要发送或接收数据的长度
**                      uiTranType    传输类型: __HC_ED_TYPE_BULK 或 __HC_ED_TYPE_INTR
**                      ucMaxTryCount 当出现错误时,最大的重试次数
** Returned value:      错误码
*********************************************************************************************************/
USB_INT8U usbDataTransfer (USB_INT8U *pucData,                          /*  数据缓冲区                  */
                           USB_INT32U uiLength,                         /*  要传输的数据长度            */
                           USB_INT8U  ucTranType,                       /*  传输类型                    */
                           USB_INT8U  ucMaxTryCount)                    /*  发生错误时最大尝试次数      */
{
    USB_INT8U                     ucErr;
    USB_INT8U                     ucTryCount;
    USB_INT32U                    uiCode;
    
    USB_INT16U                    usMaxLenPerPkt;
    USB_INT16U                    usCurTran;
    USB_INT32U                    uiTotalTran;
    USB_INT32U                    uiBufLen;
    
    USB_INT8U                    *pucBufTmp;
    USB_INT8U                    *pucFristBuf;
    
    __HC_GEN_TD_PARAM             tdParam;
    __PHC_GEN_TRANSFER_DESCRIPTOR ptdAddTd;
    __ED_INFO                     edInfo;
    
    
    if (!usbIsDeviceReady()) {
        return USB_ERR_DEVICE_NOT_READY;
    }
    
    OS_ENTER_CRITICAL();
    if (GusbHostFlags.bExitDataOperaReq) {                              /*  应用程序要求退出操作        */
        OS_EXIT_CRITICAL();
        return USB_ERR_EXIT_REQ;
    }
    
    __GusbHostEvtCnt.ucDataTranCnt++;
    OS_EXIT_CRITICAL();
    
    usbPipeOpen(ucTranType);
    __hcdGetEdInfo(ucTranType, &edInfo);
    usMaxLenPerPkt = edInfo.usMaxPktSize;
    
    OSSemPend(__GevtUsbDataTranSem, 0, &ucErr);
    
    ucTryCount = 0;
    do {
        pucBufTmp = pucData;
        
        /*
         *  设置 TD 的参数
         */
        tdParam.ucBufferRound = 1;
        tdParam.ucDelayIntr   = 0;
        tdParam.ucDataToggle  = 0;
        
        if (ucTranType & 0x80) {
            tdParam.ucDirect_PID = __OHCI_TD_TYPE_IN;
        } else {
            tdParam.ucDirect_PID = __OHCI_TD_TYPE_OUT;
        }
        
        /* 
         *  为传输添加传输描述符 TD 并启动传输
         *  当数据量比较大时可能会出现TD 不够,或缓冲区不够,此时传输要分割为多次,
         *  分割点为无法申请到空闲 TD 或申请不到缓冲区时
         */
        uiTotalTran = 0;                                                /*  清零总传输量计数器          */
        do{
            uiBufLen = 0;
            do {
                ptdAddTd = __hcdAllocTd(&edInfo);                       /*  申请 TD                     */
                if (ptdAddTd == NULL) {
                    break;
                }

                
                if (uiLength - uiTotalTran <= usMaxLenPerPkt) {
                    usCurTran = (USB_INT16U)(uiLength - uiTotalTran);
                } else {
                    usCurTran = usMaxLenPerPkt;
                }    
         
                tdParam.pucCBP = __usbAllocGenBuffer(usCurTran);    
                if (tdParam.pucCBP == NULL) {                           /*  如果现在无缓冲区可用,则,    */
                                                                        /*  ...跳出本循环               */
                    __hcdFreeTd(&edInfo, ptdAddTd);
                    break;
                }
                if (!(ucTranType & 0x80)) {                             /*  OUT 传输                    */
                    usbMemCopy(tdParam.pucCBP, pucBufTmp, usCurTran);
                    pucBufTmp = pucBufTmp + usCurTran;
                } else {                                                /*  IN 传输                     */  
                    if (uiBufLen == 0) {
                        pucFristBuf = tdParam.pucCBP;                   /*  保存第一次的缓冲区位置,     */
                    }                                                   /*  ...usbMemCopy时要用         */
                }
                tdParam.usBufLen = usCurTran;
                __hcdAddTd(&tdParam, ptdAddTd, &edInfo);                /*  将申请到的TD加入到ED中      */ 
                uiTotalTran = (USB_INT32U)(uiTotalTran + usCurTran);
                uiBufLen = (USB_INT32U)(uiBufLen + usCurTran);
            } while (uiTotalTran < uiLength);
        
            __usbEdClearSkip(ucTranType);                               /*  清除 sKip 位                */
            __hcStartSchedule(ucTranType);
            
            uiCode = (USB_INT32U)OSMboxPend(__GevtUsbDataTranMbox, USB_TIMEOUT_TICK, &ucErr);
                                                                        /*  等待调度任务处理完毕        */
            if (ucErr != OS_NO_ERR) {                                   /*  等待超时                    */
                uiCode = (USB_INT32U)(USB_ERR_TIMEOUT << 24);           /*  超时错误码                  */
                ucTryCount = (USB_INT8U)(ucMaxTryCount + 1);            /*  使当前重试次数大于最大重试  */
                                                                        /*  次数,使程序退出do while循环 */
                __hcDisEnSchedAndWaitNextFrame(ucTranType);
                __hcdEdLetHeadEquTail(&edInfo);                         /*  强制 使HeadP = TailP        */
                __hcdFreeAllTd(&edInfo);                                /*  释放所有 TD 资源            */
                __hcEnableSchedule(ucTranType);
                break;
            }
            if (uiCode == __USB_TRANDEAL_OK) {
                if ((ucTranType & 0x80)) {                              /*  IN 传输                     */
                    usbMemCopy(pucBufTmp, pucFristBuf, uiBufLen);           /*  将USB RAM里的数据拷贝至     */
                                                                        /*  ...用户缓冲区               */
                    pucBufTmp = pucBufTmp + uiBufLen;
                }
                __usbFreeGenBuffer(uiBufLen);                           /*  释放所占USB RAM缓冲区       */
            } else if (__USBLSB(uiCode, 0) == __USB_TRANDEAL_ERR_TRY) { /*  需要重试                    */
                if (__USBLSB(uiCode, 3) == USB_ERR_STALL) {            /*  端点被禁止, 需要解禁        */
                    usbClearFeature_EP(usbGetEp(0, ucTranType));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -