`
jandroid
  • 浏览: 1894832 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

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

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics