wince 2410 UDC driver 分析

在 USB Function Controller 的MDD层 有函数 GetClientFunctions( PUFN_FUNCTIONS pUfnFunctions)
调用者通过传入 PUFN_FUNCTIONS 类型的指针变量 来获得 USB Function Controller MDD层的所有操作函数.

USB Function Controller 的MDD层的函数 UFN_Init( LPCTSTR pszContext )中 会创建一个PUFN_MDD_CONTEXT pContext指针变量
这个变量包括了MDD层的所有属性,这个变量还包括了一个指向 PDD层的指针变量UFN_PDD_INTERFACE_INFO PddInfo;
PDD层的这个UFN_PDD_INTERFACE_INFO PddInfo里又包含了PDD层的一些属性和PDD层的所有操作函数指针,这样在UFN_Init()
函数中创建了一个 new CUfnBus(pszContext, pContext)USB总线对象,同时将包含MDD层所有属性的pContext指针变量作为参数,
传给CUfnBus类对象的构造函数,在它的构造函数中pContext指针对象被赋给了CUfnBus类对象的指针成员变量m_pContext
(m_pContext=pContext),之后在UFN_Init()函数中又调用PDD层的UfnPdd_InitUfnPdd_Init()函数,并将pContext指针变量中的指向
PDD层的指针变量PddInfo作为参数传给UfnPdd_InitUfnPdd_Init(),这样在UfnPdd_InitUfnPdd_Init() 函数中来实现对PddInfo指针
变量的PDD层属性和操作函数指针的赋值。因为整个过程中都是通过指针来赋值,所以CUfnBus类对象的m_pContext指针变量就能访问
MDD层的属性,PDD层的属性,PDD层的所有操作函数。

在USB Function Client驱动中的CUsbFn::Init() 函数里 调用UfnInitializeInterface()函数,并传入一些指定的指针变量参数,在
UfnInitializeInterface()函数中又 调用BusIoControl(...,IOCTL_UFN_GET_CLIENT_DATA,...) USB总线操作函数,在BusIoControl()
函数中的 CASE: IOCTL_UFN_GET_CLIENT_DATA 处理函数中 调用USB Function MDD层的全局函数GetClientFunctions(),将返回值赋给
UfnInitializeInterface()传入的参数,同时也将CUfnBus类对象的m_pContext指针变量也赋给UfnInitializeInterface()传入的参数,
这样在USB Function Client驱动程序中就可以操作的USB Function Controller驱动的MDD和PDD层所有功能。

UfnMdd_Notify -> SendDeviceNotification(pContext->lpDeviceNotify,pContext->pvDeviceNotifyParameter, dwMsg, dwParam);
USB Function Controller 的PDD层的函数UfnPdd_Init()中执行pContext->pfnNotify = pMddInterfaceInfo->pfnNotify;
这样PFN_UFN_MDD_NOTIFY pfnNotify指向UfnMdd_Notify函数指针(在UfnPdd_Init函数中执行pContext->pfnNotify = pMddInterfaceInfo->pfnNotify;);
UfnMdd_Notify函数再调用SendDeviceNotification()函数,在SendDeviceNotification()函数中最终执行(通过指针参数传入)
USB Function Controller 的MDD层的LPUFN_NOTIFY lpDeviceNotify 函数,而MDD层的lpDeviceNotify指针是在USB Function Client
驱动的函数 CUsbFn::Init()中调用dwRet = m_pUfnFuncs->lpStart(m_hDevice, DeviceNotifyStub, this, &m_hDefaultPipe);
来将USB Function Client驱动中定义的DeviceNotifyStub函数和USB Function Controller中的PDD层的pfnNotify来建立联系的

CUsbFn::DeviceNotify()->CableAttached()->OpenBulkIn()/OpenBulkOut() ->OpenPipe()->new CUsbFuncPipe ->CUsbFuncPipe::ThreadRun()->m_pSerialFn->EndpointNotification(this)
->NotifyPDDInterrupt()->SerialEventHandler(m_pMdd);

CUsbFuncPipe::ThreadRun()线程通过下面两个事件
rgh[0] = m_pTransferArray[m_dwCompleteIndex]->GetCompleteEventHandle(); //GetCompleteEventHandle() { return m_hCompleteEvent; };
rgh[1] = m_TerminateEvent;
来监测USB Function Controller端的USB中断事件,当截获中断事件后 再通过SerialEventHandler(m_pMdd)函数来处理中断事件。

CUsbFuncTransfer::CompleteNotificationStub()->CUsbFuncTransfer::CompleteNotification()->SetEvent(m_hCompleteEvent);
USB Function Controller 的MDD层的函数lpIssueTransfer()//注释:在一个管道上建立一个传输(CUsbFuncTransfer::CompleteNotificationStub是其中一个参数)
lpIssueTransfer()->CPipe::IssueTransfer()->lpIssueTransfer()->CUfnMddTransfer::Init()-> CUfnMddTransfer::m_lpNotifyRoutine = CUsbFuncTransfer::CompleteNotificationStub(); 函数指针赋值

在USB Function Controller 的PDD层的完成USB数据传输的中断处理程序中 ->CompleteTransfer()//sc2410pdd.cpp ->pContext->pfnNotify(...,UFN_MSG_TRANSFER_COMPLETE,...)
->UfnMdd_Notify(...,dwMsg,...)// 在dwMsg == UFN_MSG_TRANSFER_COMPLETE时 ->CPipe::TransferComplete()->CUfnMddTransfer::CallCompletionRoutine()
->(*CUfnMddTransfer::m_lpNotifyRoutine)(m_pvNotifyContext);

纵上分析可知在在USB Function Controller 的PDD层的完成USB数据传输后会执行CUsbFuncTransfer::CompleteNotificationStub(),并设置
事件m_hCompleteEvent为通知状态,这样来启动CUsbFuncPipe::ThreadRun()线程的执行,进而执行m_pSerialFn->EndpointNotification(this),
最终调用SerialEventHandler(m_pMdd);来根据具体的中断在USB Function Client驱动中完成相应的中断处理。如将数据从USB的硬件BUFFER中拷贝
到USB Function Client驱动所开辟的软件BUFFER中,这样以后应用程序就直接从USB Function Client驱动的软件BUFFER中拷贝数据。在这当中
函数USBSerialFn::EndpointNotification()将USB的中断类型转换为 Serial所能认识的interruptType |= INTR_TX / interruptType |= INTR_RX类型

USB Host获取描述符:
HandleEndpoint0Event()->pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_SETUP_PACKET, (DWORD) &udr);->UfnMdd_Notify()->(response =
ProcessRequest(pContext, *pUdr, dwMsg))//在CASE: UFN_MSG_PREPROCESSED_SETUP_PACKET中调用 ->ProcessGetDescriptor()/ProcessGetConfiguration()/
ProcessGetInterface()/ProcessSetAddress()/ProcessSetConfiguration()/ProcessSetInterface()等函数结构体udr中存放的是具体的从USB Host主机接受的
USB标准命令,在ProcessRequest()函数中将根据具体的udr来进行发送或设置描述符数值

 

 

几个重要数据结构的分析:
typedef class CPipe {
public:
CPipe(DWORD dwPhysicalEndpoint, PUFN_PDD_INTERFACE_INFO pPddInfo,
CFreeTransferList *pFreeTransferList);
~CPipe();

DWORD Open(UFN_BUS_SPEED Speed, PUSB_ENDPOINT_DESCRIPTOR pEndpointDesc);
DWORD Close();

BOOL IsOpen() const { return m_fOpen; }

DWORD GetPhysicalEndpoint() const { return m_dwPhysicalEndpoint; }
DWORD GetEndpointAddress() const {
DWORD dwEndpointAddress;

if (m_pFullSpeedEndpointDesc) {
dwEndpointAddress = m_pFullSpeedEndpointDesc->bEndpointAddress;
}
else if (m_pHighSpeedEndpointDesc) {
dwEndpointAddress = m_pHighSpeedEndpointDesc->bEndpointAddress;
}
else if (GetPhysicalEndpoint() == 0) {
dwEndpointAddress = 0;
}
else {
// This endpoint has not been reserved.
dwEndpointAddress = -1;
}

return dwEndpointAddress;
}

VOID Reserve(UFN_BUS_SPEED Speed, BOOL fReserve, DWORD dwInterfaceNumber,
DWORD dwEndpointIndex, PUSB_ENDPOINT_DESCRIPTOR pEndpointDesc);

BOOL IsReserved(UFN_BUS_SPEED speed) { return (m_dwReservedSpeedMask & speed) != 0; }

DWORD IssueTransfer(
LPTRANSFER_NOTIFY_ROUTINE lpNotifyRoutine,
PVOID pvNotifyContext,
DWORD dwFlags,
DWORD cbBuffer,
PVOID pvBuffer,
DWORD dwBufferPhysicalAddress,
PCUfnMddTransfer *ppTransfer,
PVOID pDMATransferInfo);

DWORD AbortTransfer(
PCUfnMddTransfer pTransfer
);

VOID AbortAllTransfers();

static DWORD GetTransferStatus(
const CUfnMddTransfer *pTransfer,
PDWORD pcbTransferred,
PDWORD pdwUsbError
);

DWORD CloseTransfer(
PCUfnMddTransfer pTransfer
);

DWORD TransferComplete(
PCUfnMddTransfer pTransfer,
BOOL fTransferWasInPdd
);

DWORD Stall();
DWORD ClearStall();

DWORD SendControlStatusHandshake();

VOID Reset() {
Lock();
DEBUGCHK(m_dwSig == UFN_PIPE_SIG);
DEBUGCHK(IsOpen() == FALSE);
DEBUGCHK(m_TransferQueue.IsEmpty());

m_dwEndpointIndex = -1;
m_dwInterfaceNumber = -1;
m_dwReservedSpeedMask = 0;
m_pFullSpeedEndpointDesc = NULL;
m_pHighSpeedEndpointDesc = NULL;
Unlock();
}

VOID FreeTransfer(
PCUfnMddTransfer pTransfer
);

static DWORD ValidatePipeHandle(const CPipe *pPipe);

#ifdef DEBUG
VOID Validate();
#else
VOID Validate() {}
#endif

private:
VOID Lock() {
EnterCriticalSection(&m_cs);

#ifdef DEBUG
if (m_dwLockCount++ == 0) {
m_dwThreadId = GetCurrentThreadId();
}
#endif
}

VOID Unlock() {
#ifdef DEBUG
if (--m_dwLockCount == 0) {
m_dwThreadId = 0;
}
#endif

LeaveCriticalSection(&m_cs);
}

DWORD m_dwSig;
CRITICAL_SECTION m_cs;
BOOL m_fOpen;
PUFN_PDD_INTERFACE_INFO m_pPddInfo;
CTransferQueue<CUfnMddTransfer> m_TransferQueue;
CFreeTransferList *m_pFreeTransferList;

DWORD m_dwPhysicalEndpoint; // PDD endpoint index (0 based)
DWORD m_dwEndpointIndex; // Index into the UFN_CONFIGURATION tree
DWORD m_dwInterfaceNumber; // Number of the interface in descriptor
DWORD m_dwReservedSpeedMask;

PUSB_ENDPOINT_DESCRIPTOR m_pFullSpeedEndpointDesc;
PUSB_ENDPOINT_DESCRIPTOR m_pHighSpeedEndpointDesc;

#ifdef DEBUG
DWORD m_dwThreadId;
DWORD m_dwLockCount;
#endif
} *PCPipe;

//每个PiPe都和一个USB Device的端点关联,保存着此端点的Index序号(0 based),此端点的描述符的首地址

//在USB枚举阶段,enum.cpp中SetupTx(pContext, (PBYTE) pvBuffer, cbBuffer, udr.wLength)函数的参数
//pvBuffer:要发送数据的内存首地址.
//cbBuffer:USB Device要发送数据的大小(有可能和USB Host需要的 udr.wLength不一样,比如说配置描述符,Host要0xff数量,而Device全部的描述符大小为0x32,所以此值为0x32)
//udr.wLength:USB Host需要USB Device传输的字节数
//这个函数将使用PCPipe pPipeEndpoint0 = &pContext->pPipes[0];并将Pipe参数传入UfnMdd_IssueTransfer

//UfnMdd_IssueTransfer 再调用CPipe::IssueTransfer,这两个IssueTransfer函数中的cbBuffer 是指 min(udr.wLength,cbBuffer)即(Host需要的和Device要发送的字节数两者的最小值)
//CPipe::IssueTransfer 初始化一个PCUfnMddTransfer pTransfer,将MDD层传下来的参数存入类变量pTransfer中,将cbBuffer和pvBuffer存入pTransfer类中的类型为 STransfer的成员变量m_PddTransfer中,然后将
//PDD层的设备pContext,需要传输的端点号,和存有 cbBuffer,pvBuffer,cbTransferred(已经传送的字节数,初始化为0)的参数pTransfer作为参数传入 UfnPdd_IssueTransfer();UfnPdd_IssueTransfer()->StartTransfer->HandleTx/HandleRx


typedef class CUfnMddTransfer {
public:
CUfnMddTransfer() {
ClearMembers();
m_dwSig = UFN_TRANSFER_SIG;
m_lRefCnt = 0;
}

~CUfnMddTransfer() {
DEBUGCHK( m_dwSig == UFN_TRANSFER_SIG ||
m_dwSig == UFN_FREE_TRANSFER_SIG );
m_dwSig = GARBAGE_DWORD;
}

VOID MarkAsFree() {
DEBUGCHK(m_dwSig == UFN_TRANSFER_SIG);
DEBUGCHK(m_fInPdd == FALSE);
DEBUGCHK(m_lRefCnt == 0);
ClearMembers();
m_dwSig = UFN_FREE_TRANSFER_SIG;
}

VOID MarkAsValid() {
DEBUGCHK(m_dwSig == UFN_FREE_TRANSFER_SIG);
m_dwSig = UFN_TRANSFER_SIG;
m_lRefCnt = 0;
}

VOID AddRef();
VOID Release();

VOID Init(DWORD dwFlags, PVOID pvBuffer, DWORD dwBufferPhysicalAddress,
DWORD cbBuffer, PVOID pvPddTransferInfo,
LPTRANSFER_NOTIFY_ROUTINE lpNotifyRoutine, PVOID pvNotifyContext,
PCPipe pPipe);

PCPipe GetPipe() { return m_pPipe; }

BOOL IsInPdd() { return m_fInPdd; }
VOID EnteringPdd() {
DEBUGCHK(m_fInPdd == FALSE);
AddRef();
m_fInPdd = TRUE;
}

VOID LeavingPdd() {
DEBUGCHK(m_fInPdd == TRUE);
m_fInPdd = FALSE;
Release();
}

VOID CallCompletionRoutine();

DWORD GetDwUsbError() const { return m_PddTransfer.dwUsbError; }
DWORD GetCbBuffer() const { return m_PddTransfer.cbBuffer; }
PVOID GetPvBuffer() const { return m_PddTransfer.pvBuffer; }
DWORD GetDwFlags() const { return m_PddTransfer.dwFlags; }
DWORD GetCbTransferred() const { return m_PddTransfer.cbTransferred; }

PSTransfer GetPddTransfer() { return &m_PddTransfer; }

VOID SetDwUsbError(DWORD dwUsbError) {
DEBUGCHK(!IsComplete());
m_PddTransfer.dwUsbError = dwUsbError;
}

BOOL IsComplete() { return (GetDwUsbError() != UFN_NOT_COMPLETE_ERROR); }

#ifdef DEBUG
VOID Validate() {
DEBUGCHK(m_dwSig == UFN_TRANSFER_SIG);
DEBUGCHK(m_pPipe);
DEBUGCHK(!GetCbBuffer() || GetPvBuffer());
}
#else
VOID Validate() {}
#endif

static CUfnMddTransfer* ConvertFromPddTransfer(PSTransfer pPddTransfer);

static DWORD ReferenceTransferHandle(CUfnMddTransfer *pTransfer);

private:
#ifdef DEBUG
VOID ClearMembers() {
memset(this, GARBAGE_DWORD, sizeof(*this));
}
#else
VOID ClearMembers() {}
#endif

DWORD m_dwSig;
LONG m_lRefCnt;
PCPipe m_pPipe;
BOOL m_fInPdd;

LPTRANSFER_NOTIFY_ROUTINE m_lpNotifyRoutine;
PVOID m_pvNotifyContext;

STransfer m_PddTransfer;
} *PCUfnMddTransfer;


// Transfer structure passed to the PDD from the MDD in IssueTransfer.
typedef struct _STransfer {
DWORD dwCallerPermissions;
DWORD dwFlags;
PVOID pvBuffer; //要发送数据的内存首地址
DWORD dwBufferPhysicalAddress;
DWORD cbBuffer; //此次传输需要传送的字节数,min(udr.wLength,cbBuffer)即(Host需要的和Device要发送的字节数两者的最小值)
DWORD cbTransferred; //已经传输完成的字节数
DWORD dwUsbError; // Possible values are in usbfntypes.h

PVOID pvPddData; // PDD can do whatever it likes with this
PVOID pvPddTransferInfo; // Specific to PDD from client
} STransfer, *PSTransfer;


typedef struct EP_STATUS {
DWORD dwEndpointNumber;
DWORD dwDirectionAssigned;
DWORD dwPacketSizeAssigned;
BOOL fInitialized;
DWORD dwEndpointType;
PSTransfer pTransfer;
CRITICAL_SECTION cs;
} *PEP_STATUS;

//这个结构体保存着一个端点传输中的基本信息:端点的Index号,传输方向,每次最大传输数量,端点的类型,此次传输的数据存放内存首地址
//需要传输的数量,已经传输的数量(这三个信息包存在成员变量PSTransfer中)
// 这个结构体中的PSTransfer指针的赋值是在PDD的StartTransfer(PCTRLR_PDD_CONTEXT pContext,PEP_STATUS peps,PSTransfer pTransfer)函数中peps->pTransfer = pTransfer;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值