WinCE USB 驱动中IssueTransfer调用相关

IssueTransfer调用相关

 

在CHub类中的AttachDevice函数中,经常会调用到类CControlPipe的函数IssueTransfer。本文介绍一下函数CControlPipe::IssueTransfer的调用过程,以及具体实现。

 

首先说说对函数CControlPipe::IssueTransfer的调用。

 

首先调用函数CControlPipe::IssueTransfer:

    status = pControlPipe->IssueTransfer(

        .

        .

        .

        TransferDoneCallbackSetEvent, // 回调函数

        m_hHubStatusChangeEvent, // 回调函数的参数

        .

        .

        .

     ); 

 

    传输处理完后,会使用传入的回调函数参数来调用回调函数。即set event m_hHubStatusChangeEvent。

 

等待事件m_hHubStatusChangeEvent,即等待传输处理结束。

    WaitForSingleObject( m_hHubStatusChangeEvent, ATTACH_TIMEOUT )

 

    若Timeout,则中断传输:

        pControlPipe->AbortTransfer( NULL, // callback function

                                     NULL, // callback parameter

                                     this ); // cancel ID

 

判断线程退出标志,若为True,则中断传输:

    pControlPipe->AbortTransfer( NULL, // callback function

                                 NULL, // callback parameter

                                 this ); // cancel ID

 

 

下面来说说函数CControlPipe::IssueTransfer的实现。

 

首先判断是否需要change address:

        if (m_bDeviceAddress ==0 && address !=0) { // Address Changed.m_bDeviceAddress在类CPipe的构造函数中被初始化。请参考Pipe相关类的继承关系。

            // CQueuedPipe的构造函数中,将m_pQueuedTransfer赋值为NULL。

            // 函数CQueuedPipe::AbortTransfer和函数CQueuedPipe::AbortQueue中会根据条件,将m_pQueuedTransfer赋值为NULL。

            // 函数CQueuedPipe::ScheduleTransfer中会取m_pUnQueuedTransfer的第一个,赋值给m_pQueuedTransfer。

            // 函数CQueuedPipe::CheckForDoneTransfers中,如果Pipe Halt了,会将m_pQueuedTransfer赋值为NULL。

            // m_pPipeQHead在函数CControlPipe::OpenPipe中被创建

            if ( m_pQueuedTransfer == NULL &&  m_pPipeQHead && m_pPipeQHead->IsActive()==FALSE) { // We need cqueue new Transfer.

                m_bDeviceAddress = address;

                // 函数CQH::SetDeviceAddress的实现:qH_StaticEndptState.qH_SESContext.DeviceAddress = dwDeviceAddress;

                m_pPipeQHead ->SetDeviceAddress(m_bDeviceAddress);

            }

            else {

                ASSERT(FALSE);

                return requestFailed;

            }

        }

 

接下来调用函数CQueuedPipe::IssueTransfer。

 

函数CQueuedPipe::IssueTransfer中:

 

    根据传入的参数定义一个STransfer对象。

 

    检查STransfer对象中的Transfer参数是否合法。

        AreTransferParametersValid(&sTransfer)

 

    判断QHead是否已经创建成功。

 

    检查成员变量m_bDeviceAddress与传入的address是否一致。

 

    如果以上条件满足。则:

 

        进入临界区。

 

        Disables the PREfast warnings 

            #pragma prefast(disable: 322, "Recover gracefully from hardware failure")

 

        进入一个__try... __except模块。

        在该模块中,执行以下操作:

 

            初始化Transfer状态参数。

 

            用当前对象的this指针和先前创建的Transfer对象在CEhcd对象的Physical Memory上创建一个CQTransfer对象。CQTransfer是CTransfer的子类。

                CQTransfer * pTransfer = new CQTransfer(this,m_pCEhcd->GetPhysMem(),sTransfer);

 

            如果创建成功,调用CQTransfer对象的Init函数。

                pTransfer->Init()

 

                函数CTransfer::Init中检查是否需要分配Control Header Memory和Data Buffer。若需要,则进行分配。

 

            若函数函数CTransfer::Init调用成功,则声明一个CQTransfer指针,并将其指向m_pUnQueuedTransfer。

 

            接下来就是将新创建的Transfer对象追加到m_pUnQueuedTransfer末尾。

 

        执行完后,恢复PREfast warnings

            #pragma prefast(pop)

 

        退出临界区。

 

        调用函数CQueuedPipe::ScheduleTransfer。

 

 

函数CQueuedPipe::ScheduleTransfe执行的操作如下:

 

    首先判断是否需要queue new Transfer,若不需要,则不进行任何操作。

    判断的条件是m_pQueuedTransfer为空,m_pUnQueuedTransfer非空。QHead存在,并且不是Active的。

 

    从m_pUnQueuedTransfer中取出第一个Transfer对象。

 

    调用函数CQTransfer::GetCQTDList获取m_pCQTDList。

 

        在函数CQTransfer::AddTransfer中会对m_pCQTDList赋值。

            m_pCQTDList = new(m_pCPhysMem) CQTD(this, ((CQueuedPipe * const)m_pCPipe)->GetQHead())

            pPrevTD= m_pCQTDList = pCurTD;

 

    调用函数CQH::QueueTD,将QHead的nextQTDPointer指向前面获取到底m_pCQTDList。

        GetQHead()->QueueTD(pCurTransfer->GetCQTDList())

 

    将先前从m_pUnQueuedTransfer中取出的Transfer对象赋值给m_pQueuedTransfer。

        m_pQueuedTransfer = pCurTransfer;

 

++参考+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

1、Pipe相关类的继承关系

//                               CPipe (ADT)

//                           /                          /

//                  CQueuedPipe (ADT)       CIsochronousPipe

//                /                  |             / 

//              /                    |               /

//   CControlPipe   CInterruptPipe  CBulkPipe

posted @ 2011-04-22 18:20  andriod2012  阅读(294)  评论(0编辑  收藏  举报