wince5使用access数据库_Windows CE USB Function Driver驱动简析(1)-驱动架构及UfnPdd函数(基于WinCE5.0&...

s3c2410有2个USB Host接口,一个Device接口.首先介绍下USB的几个概念:

USB是主从结构的,PC是主端(Host),连接到PC上的设备就是从端(device或function).因此对应的驱动分别叫做USB

Host Driver及USB Function

Driver。我们的板子可以做host也可以做device,接U盘,鼠标到板子上,板子就是Host.板子连到PC作为Mass

Storage或者用Activesync连接就是function.

USB驱动结构图示:

a4c26d1e5885305701be709a3d33442f.png

这里我们实现的USB Function Driver就是板子和PC连接时板子端的USB驱动.USB Function

Driver包括Controller Driver和Client Driver.Controller

Driver介于硬件和Client Driver直之间的控制层,而Client Driver则是具体的应用,如Mass

Storage,RNDIS,Serial Class.

USB Function Driver包括MDD和PDD层,SMDK2410

BSP中的USBFN驱动实际上就是PDD部分.MDD部分在/WINCE500/PUBLIC/COMMON/OAK/DRIVERS/USBFN/CONTROLLER/MDD.在我们的PDD驱动中通过链接ufnmddbase.lib这个MDD库来生成驱动dll.

这里我们主要来看看USB Function Driver的PDD部分.实际上就一个文件,sc2410pdd.cpp.

USB Function

Driver也是一个标准的流接口驱动,流接口函数实现在/WINCE500/PUBLIC/COMMON/OAK/DRIVERS/USBFN/CONTROLLER/MDD/ufnmdd.cpp中.如UFN_***的函数,会调用在PDD中实现的函数.

1.UfnPdd_DllEntry

被MDD层的DllEntry调用,仅仅设置了g_pUDCBase为NULL.

// Called by MDD's DllEntry.

extern"C"

BOOL

UfnPdd_DllEntry(

HANDLE hDllHandle,

DWORD dwReason,

LPVOID lpReserved

)

{

SETFNAME();

switch(dwReason) {

caseDLL_PROCESS_ATTACH:

g_pUDCBase = NULL;

break;

}

returnTRUE;

}

// Called by MDD's DllEntry.

extern "C"

BOOL

UfnPdd_DllEntry(

HANDLE hDllHandle,

DWORD dwReason,

LPVOID lpReserved

)

{

SETFNAME();

switch (dwReason) {

case DLL_PROCESS_ATTACH:

g_pUDCBase = NULL;

break;

}

return TRUE;

}

2.UfnPdd_Init

这个会被MDD层的Init函数调用,首先初始化一个UFN_PDD_INTERFACE_INFO

接口的数组,里面定义了很多函数指针,这些PDD函数都会被MDD层调用.这些函数后面一一分析.

该结构原型如下:

// Structure that the PDD must fill out in UfnPdd_Init.

typedefstruct_UFN_PDD_INTERFACE_INFO {

DWORD dwVersion;

DWORD dwCapabilities;

DWORD dwEndpointCount;

PVOID pvPddContext;

PFN_UFN_PDD_DEINIT pfnDeinit;

PFN_UFN_PDD_IS_CONFIGURATION_SUPPORTABLE pfnIsConfigurationSupportable;

PFN_UFN_PDD_IS_ENDPOINT_SUPPORTABLE pfnIsEndpointSupportable;

PFN_UFN_PDD_INIT_ENDPOINT pfnInitEndpoint;

PFN_UFN_PDD_REGISTER_DEVICE pfnRegisterDevice;

PFN_UFN_PDD_DEREGISTER_DEVICE pfnDeregisterDevice;

PFN_UFN_PDD_START pfnStart;

PFN_UFN_PDD_STOP pfnStop;

PFN_UFN_PDD_ISSUE_TRANSFER pfnIssueTransfer;

PFN_UFN_PDD_ABORT_TRANSFER pfnAbortTransfer;

PFN_UFN_DEINIT_ENDPOINT pfnDeinitEndpoint;

PFN_UFN_STALL_ENDPOINT pfnStallEndpoint;

PFN_UFN_CLEAR_ENDPOINT_STALL pfnClearEndpointStall;

PFN_UFN_SEND_CONTROL_STATUS_HANDSHAKE pfnSendControlStatusHandshake;

PFN_UFN_SET_ADDRESS pfnSetAddress;

PFN_UFN_IS_ENDPOINT_HALTED pfnIsEndpointHalted;

PFN_UFN_INITIATE_REMOTE_WAKEUP pfnInitiateRemoteWakeup;

PFN_UFN_POWER_DOWN pfnPowerDown;

PFN_UFN_POWER_UP pfnPowerUp;

PFN_UFN_IOCONTROL pfnIOControl;

} UFN_PDD_INTERFACE_INFO, *PUFN_PDD_INTERFACE_INFO;

// Structure that the PDD must fill out in UfnPdd_Init.

typedef struct _UFN_PDD_INTERFACE_INFO {

DWORD dwVersion;

DWORD dwCapabilities;

DWORD dwEndpointCount;

PVOID pvPddContext;

PFN_UFN_PDD_DEINIT pfnDeinit;

PFN_UFN_PDD_IS_CONFIGURATION_SUPPORTABLE pfnIsConfigurationSupportable;

PFN_UFN_PDD_IS_ENDPOINT_SUPPORTABLE pfnIsEndpointSupportable;

PFN_UFN_PDD_INIT_ENDPOINT pfnInitEndpoint;

PFN_UFN_PDD_REGISTER_DEVICE pfnRegisterDevice;

PFN_UFN_PDD_DEREGISTER_DEVICE pfnDeregisterDevice;

PFN_UFN_PDD_START pfnStart;

PFN_UFN_PDD_STOP pfnStop;

PFN_UFN_PDD_ISSUE_TRANSFER pfnIssueTransfer;

PFN_UFN_PDD_ABORT_TRANSFER pfnAbortTransfer;

PFN_UFN_DEINIT_ENDPOINT pfnDeinitEndpoint;

PFN_UFN_STALL_ENDPOINT pfnStallEndpoint;

PFN_UFN_CLEAR_ENDPOINT_STALL pfnClearEndpointStall;

PFN_UFN_SEND_CONTROL_STATUS_HANDSHAKE pfnSendControlStatusHandshake;

PFN_UFN_SET_ADDRESS pfnSetAddress;

PFN_UFN_IS_ENDPOINT_HALTED pfnIsEndpointHalted;

PFN_UFN_INITIATE_REMOTE_WAKEUP pfnInitiateRemoteWakeup;

PFN_UFN_POWER_DOWN pfnPowerDown;

PFN_UFN_POWER_UP pfnPowerUp;

PFN_UFN_IOCONTROL pfnIOControl;

} UFN_PDD_INTERFACE_INFO, *PUFN_PDD_INTERFACE_INFO;

接下来就是读取注册表获取相关配置信息,存到一个PCTRLR_PDD_CONTEXT结构pContext中.一开始初始化一些符号,还有MDD

Context等.然后设置每个ENDPOINT对应的端点状态结构EP_STATUS的端点号,这里最多5个端点,也就是有5个EP_STATUS的结构.

接下来定义了DDKISRINFO和DDKWINDOWINFO的对象,用来读取注册表信IoBase,IoLen,Irq,并向内核申请一个SYSINTR逻辑中断号.然后读取IST优先级("Priority256"=dword:64),接着创建一个访问总线句柄pContext->hBusAccess.

最后调用MapRegisterSet将IOBASE地址(USB device controller

register地址)映射到虚拟地址空间.真正的g_pUDCBase是加上了0x140(UDC寄存器基址偏移)的偏移.

然后设置attachedState为UFN_DETACH.调用ResetDevice复位UDC寄存器.将sc_PddInterfaceInfo传递给输入参数.

如果中间出现任何错误将跳转至EXIT,RegCloseKey关闭注册表,FreeCtrlrContext释放之前分配的资源.

// Initialize the device.

DWORD

WINAPI

UfnPdd_Init(

LPCTSTR pszActiveKey,

PVOID pvMddContext,

PUFN_MDD_INTERFACE_INFO pMddInterfaceInfo,

PUFN_PDD_INTERFACE_INFO pPddInterfaceInfo

)

{

SETFNAME();

FUNCTION_ENTER_MSG();

staticconstUFN_PDD_INTERFACE_INFO sc_PddInterfaceInfo = {

UFN_PDD_INTERFACE_VERSION,

UFN_PDD_CAPS_SUPPORTS_FULL_SPEED,

ENDPOINT_COUNT,

NULL,// This gets filled in later

&UfnPdd_Deinit,

&UfnPdd_IsConfigurationSupportable,

&UfnPdd_IsEndpointSupportable,

&UfnPdd_InitEndpoint,

&UfnPdd_RegisterDevice,

&UfnPdd_DeregisterDevice,

&UfnPdd_Start,

&UfnPdd_Stop,

&UfnPdd_IssueTransfer,

&UfnPdd_AbortTransfer,

&UfnPdd_DeinitEndpoint,

&UfnPdd_StallEndpoint,

&UfnPdd_ClearEndpointStall,

&UfnPdd_SendControlStatusHandshake,

&UfnPdd_SetAddress,

&UfnPdd_IsEndpointHalted,

&UfnPdd_InitiateRemoteWakeup,

&UfnPdd_PowerDown,

&UfnPdd_PowerUp,

&UfnPdd_IOControl,

};

DWORD dwType;

DWORD dwRet;

HKEY hkDevice = NULL;

PCTRLR_PDD_CONTEXT pContext = NULL;

DEBUGCHK(pszActiveKey);

DEBUGCHK(pMddInterfaceInfo);

DEBUGCHK(pPddInterfaceInfo);

hkDevice = OpenDeviceKey(pszActiveKey);

if(!hkDevice) {

dwRet = GetLastError();

DEBUGMSG(ZONE_ERROR, (_T("%s Could not open device key. Error: %d/r/n"),

pszFname, dwRet));

gotoEXIT;

}

pContext = (PCTRLR_PDD_CONTEXT) LocalAlloc(LPTR,sizeof(*pContext));

if(pContext == NULL) {

dwRet = GetLastError();

PREFAST_DEBUGCHK(dwRet != ERROR_SUCCESS);

DEBUGMSG(ZONE_ERROR, (_T("%s LocalAlloc failed. Error: %d/r/n"), pszFname, dwRet));

gotoEXIT;

}

pContext->dwSig = SC2410_SIG;

pContext->pvMddContext = pvMddContext;

pContext->cpsCurrent = D4;

pContext->dwIrq = IRQ_UNSPECIFIED;

pContext->pfnNotify = pMddInterfaceInfo->pfnNotify;

InitializeCriticalSection(&pContext->csIndexedRegisterAccess);

for(DWORD dwEp = 0; dwEp rgEpStatus); ++dwEp) {

pContext->rgEpStatus[dwEp].dwEndpointNumber = dwEp;

}

DWORD dwDataSize;

DWORD dwPriority;

DDKISRINFO dii;

DDKWINDOWINFO dwi;

// read window configuration from the registry

dwi.cbSize =sizeof(dwi);

dwRet = DDKReg_GetWindowInfo(hkDevice, &dwi);

if(dwRet != ERROR_SUCCESS) {

DEBUGMSG(ZONE_ERROR, (_T("%s DDKReg_GetWindowInfo() failed %d/r/n"),

pszFname, dwRet));

gotoEXIT;

}

elseif(dwi.dwNumIoWindows != 1) {

DEBUGMSG(ZONE_ERROR, (_T("%s %d windows configured, expected 1/r/n"),

pszFname, dwi.dwNumIoWindows));

dwRet = ERROR_INVALID_DATA;

gotoEXIT;

}

elseif(dwi.ioWindows[0].dwLen 

DEBUGMSG(ZONE_INIT, (_T("%s ioLen of 0x%x is less than required 0x%x/r/n"),

pszFname, dwi.ioWindows[0].dwLen, REGISTER_SET_SIZE));

dwRet = ERROR_INVALID_DATA;

gotoEXIT;

}

elseif(dwi.ioWindows[0].dwBase == 0){

DEBUGMSG(ZONE_INIT, (_T("%s no ioBase value specified/r/n"),pszFname));

dwRet = ERROR_INVALID_DATA;

gotoEXIT;

}

else{

pContext->dwIOBase = dwi.ioWindows[0].dwBase;

pContext->dwIOLen = dwi.ioWindows[0].dwLen;

}

// get ISR configuration information

dii.cbSize =sizeof(dii);

dwRet = DDKReg_GetIsrInfo(hkDevice, &dii);

if(dwRet != ERROR_SUCCESS) {

DEBUGMSG(ZONE_ERROR, (_T("%s DDKReg_GetIsrInfo() failed %d/r/n"),

pszFname, dwRet));

gotoEXIT;

}

elseif( (dii.dwSysintr == SYSINTR_NOP) && (dii.dwIrq == IRQ_UNSPECIFIED) ) {

DEBUGMSG(ZONE_ERROR, (_T("%s no IRQ or SYSINTR value specified/r/n"), pszFname));

dwRet = ERROR_INVALID_DATA;

gotoEXIT;

}

else{

if(dii.dwSysintr == SYSINTR_NOP) {

BOOL fSuccess = KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dii.dwIrq,

sizeof(DWORD), &dii.dwSysintr,sizeof(DWORD), NULL);

if(!fSuccess) {

DEBUGMSG(ZONE_ERROR, (_T("%s IOCTL_HAL_REQUEST_SYSINTR failed!/r/n"),

pszFname));

gotoEXIT;

}

pContext->dwIrq = dii.dwIrq;

pContext->dwSysIntr = dii.dwSysintr;

}

else{

pContext->dwSysIntr = dii.dwSysintr;

}

}

// Read the IST priority

dwDataSize =sizeof(dwPriority);

dwRet = RegQueryValueEx(hkDevice, UDC_REG_PRIORITY_VAL, NULL, &dwType,

(LPBYTE) &dwPriority, &dwDataSize);

if(dwRet != ERROR_SUCCESS) {

dwPriority = DEFAULT_PRIORITY;

}

pContext->hBusAccess = CreateBusAccessHandle(pszActiveKey);

if(pContext->hBusAccess == NULL) {

// This is not a failure.

DEBUGMSG(ZONE_WARNING, (_T("%s Could not create bus access handle/r/n"),

pszFname));

}

DEBUGMSG(ZONE_INIT, (_T("%s Using IO Base %x/r/n"),

pszFname, pContext->dwIOBase));

DEBUGMSG(ZONE_INIT, (_T("%s Using SysIntr %u/r/n"),

pszFname, pContext->dwSysIntr));

DEBUGMSG(ZONE_INIT, (_T("%s Using IST priority %u/r/n"),

pszFname, dwPriority));

pContext->dwISTPriority = dwPriority;

// map register space to virtual memory

dwRet = MapRegisterSet(pContext);

if(dwRet != ERROR_SUCCESS) {

DEBUGMSG(ZONE_ERROR, (_T("%s failed to map register space/r/n"),

pszFname));

gotoEXIT;

}

pContext->attachedState = UFN_DETACH;

ResetDevice(pContext);

ValidateContext(pContext);

memcpy(pPddInterfaceInfo, &sc_PddInterfaceInfo,sizeof(sc_PddInterfaceInfo));

pPddInterfaceInfo->pvPddContext = pContext;

EXIT:

if(hkDevice) RegCloseKey(hkDevice);

if(dwRet != ERROR_SUCCESS && pContext) {

FreeCtrlrContext(pContext);

}

FUNCTION_LEAVE_MSG();

returndwRet;

}

// Initialize the device.

DWORD

WINAPI

UfnPdd_Init(

LPCTSTR pszActiveKey,

PVOID pvMddContext,

PUFN_MDD_INTERFACE_INFO pMddInterfaceInfo,

PUFN_PDD_INTERFACE_INFO pPddInterfaceInfo

)

{

SETFNAME();

FUNCTION_ENTER_MSG();

static const UFN_PDD_INTERFACE_INFO sc_PddInterfaceInfo = {

UFN_PDD_INTERFACE_VERSION,

UFN_PDD_CAPS_SUPPORTS_FULL_SPEED,

ENDPOINT_COUNT,

NULL, // This gets filled in later

&UfnPdd_Deinit,

&UfnPdd_IsConfigurationSupportable,

&UfnPdd_IsEndpointSupportable,

&UfnPdd_InitEndpoint,

&UfnPdd_RegisterDevice,

&UfnPdd_DeregisterDevice,

&UfnPdd_Start,

&UfnPdd_Stop,

&UfnPdd_IssueTransfer,

&UfnPdd_AbortTransfer,

&UfnPdd_DeinitEndpoint,

&UfnPdd_StallEndpoint,

&UfnPdd_ClearEndpointStall,

&UfnPdd_SendControlStatusHandshake,

&UfnPdd_SetAddress,

&UfnPdd_IsEndpointHalted,

&UfnPdd_InitiateRemoteWakeup,

&UfnPdd_PowerDown,

&UfnPdd_PowerUp,

&UfnPdd_IOControl,

};

DWORD dwType;

DWORD dwRet;

HKEY hkDevice = NULL;

PCTRLR_PDD_CONTEXT pContext = NULL;

DEBUGCHK(pszActiveKey);

DEBUGCHK(pMddInterfaceInfo);

DEBUGCHK(pPddInterfaceInfo);

hkDevice = OpenDeviceKey(pszActiveKey);

if (!hkDevice) {

dwRet = GetLastError();

DEBUGMSG(ZONE_ERROR, (_T("%s Could not open device key. Error: %d/r/n"),

pszFname, dwRet));

goto EXIT;

}

pContext = (PCTRLR_PDD_CONTEXT) LocalAlloc(LPTR, sizeof(*pContext));

if (pContext == NULL) {

dwRet = GetLastError();

PREFAST_DEBUGCHK(dwRet != ERROR_SUCCESS);

DEBUGMSG(ZONE_ERROR, (_T("%s LocalAlloc failed. Error: %d/r/n"), pszFname, dwRet));

goto EXIT;

}

pContext->dwSig = SC2410_SIG;

pContext->pvMddContext = pvMddContext;

pContext->cpsCurrent = D4;

pContext->dwIrq = IRQ_UNSPECIFIED;

pContext->pfnNotify = pMddInterfaceInfo->pfnNotify;

InitializeCriticalSection(&pContext->csIndexedRegisterAccess);

for (DWORD dwEp = 0; dwEp < dim(pContext->rgEpStatus); ++dwEp) {

pContext->rgEpStatus[dwEp].dwEndpointNumber = dwEp;

}

DWORD dwDataSize;

DWORD dwPriority;

DDKISRINFO dii;

DDKWINDOWINFO dwi;

// read window configuration from the registry

dwi.cbSize = sizeof(dwi);

dwRet = DDKReg_GetWindowInfo(hkDevice, &dwi);

if(dwRet != ERROR_SUCCESS) {

DEBUGMSG(ZONE_ERROR, (_T("%s DDKReg_GetWindowInfo() failed %d/r/n"),

pszFname, dwRet));

goto EXIT;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值