📄 ufnmdd.cpp
字号:
}
if (pContext->fPddInitialized) {
// Deinitialize the PDD
pContext->PddInfo.pfnDeinit(pContext->PddInfo.pvPddContext);
}
if (pContext->hKey) RegCloseKey(pContext->hKey);
DEBUGCHK(pContext->hEnumTransfer == NULL);
if (pContext->hevReadyForNotifications) CloseHandle(pContext->hevReadyForNotifications);
if (pContext->pOpenList) delete pContext->pOpenList;
DeleteCriticalSection(&pContext->csMddAccess);
DeleteCriticalSection(&pContext->csBusIoctlAccess);
if (pContext->hParentBusHandle) {
CloseBusAccessHandle(pContext->hParentBusHandle);
}
pContext->dwSig = GARBAGE_DWORD;
LocalFree(pContext);
FUNCTION_LEAVE_MSG();
}
static
BOOL
IsPddInterfaceInfoValid(
PUFN_PDD_INTERFACE_INFO pPddInterfaceInfo
)
{
BOOL fRet = TRUE;
if ( !pPddInterfaceInfo ||
pPddInterfaceInfo->dwVersion != UFN_PDD_INTERFACE_VERSION ||
pPddInterfaceInfo->dwEndpointCount == 0 ||
(pPddInterfaceInfo->dwCapabilities & UFN_PDD_CAPS_SUPPORTS_FULL_SPEED) == 0 ||
!pPddInterfaceInfo->pfnDeinit ||
!pPddInterfaceInfo->pfnIsConfigurationSupportable ||
!pPddInterfaceInfo->pfnIsEndpointSupportable ||
!pPddInterfaceInfo->pfnInitEndpoint ||
!pPddInterfaceInfo->pfnRegisterDevice ||
!pPddInterfaceInfo->pfnDeregisterDevice ||
!pPddInterfaceInfo->pfnStart ||
!pPddInterfaceInfo->pfnStop ||
!pPddInterfaceInfo->pfnIssueTransfer ||
!pPddInterfaceInfo->pfnAbortTransfer ||
!pPddInterfaceInfo->pfnDeinitEndpoint ||
!pPddInterfaceInfo->pfnStallEndpoint ||
!pPddInterfaceInfo->pfnClearEndpointStall ||
!pPddInterfaceInfo->pfnSendControlStatusHandshake ||
!pPddInterfaceInfo->pfnSetAddress ||
!pPddInterfaceInfo->pfnIsEndpointHalted ||
!pPddInterfaceInfo->pfnInitiateRemoteWakeup ||
!pPddInterfaceInfo->pfnPowerDown ||
!pPddInterfaceInfo->pfnPowerUp ||
!pPddInterfaceInfo->pfnIOControl ) {
fRet = FALSE;
}
return fRet;
}
// Initialize the MDD, PDD, and client.
extern "C"
DWORD
UFN_Init(
LPCTSTR pszContext
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DWORD dwErr;
PUFN_MDD_CONTEXT pContext = NULL;
CReg regActive;
UFN_MDD_INTERFACE_INFO MddInterfaceInfo = {
UFN_PDD_INTERFACE_VERSION, &UfnMdd_Notify
};
DEBUGCHK(pszContext);
// If this DEBUGCHK fires, that means that the MDD's DllEntry
// is not being called. Please verify that you are using that
// entry point and step through it in the debugger.
DEBUGCHK(CTransferQueue<CUfnMddTransfer>::InitializeClassCalled());
if (!regActive.Open(HKEY_LOCAL_MACHINE, pszContext)) {
DEBUGMSG(ZONE_ERROR, (_T("%s Failed to open active key\r\n"), pszFname));
goto EXIT;
}
// Allocate our context
pContext = (PUFN_MDD_CONTEXT) LocalAlloc(LPTR, sizeof(*pContext));
if (pContext == NULL) {
DEBUGMSG(ZONE_ERROR, (_T("%s LocalAlloc failed. Error: %d\r\n"), pszFname,
GetLastError()));
goto EXIT;
}
pContext->dwSig = UFN_MDD_SIG;
pContext->Speed = BS_UNKNOWN_SPEED;
pContext->uOTGCapabilityBits = 0 ;
pContext->hParentBusHandle = CreateBusAccessHandle(pszContext ) ;
if (pContext->hParentBusHandle) {
if (!BusChildIoControl(pContext->hParentBusHandle, IOCTL_BUS_USBOTG_GETOTG_ENABLE_BIT, &(pContext->uOTGCapabilityBits),sizeof(pContext->uOTGCapabilityBits)))
pContext->uOTGCapabilityBits = 0 ;
}
InitializeCriticalSection(&pContext->csMddAccess);
InitializeCriticalSection(&pContext->csBusIoctlAccess);
pContext->pOpenList = new COpenList();
if (pContext->pOpenList == NULL) {
DEBUGMSG(ZONE_ERROR, (_T("%s new failed. Error: %d\r\n"), pszFname,
GetLastError()));
goto EXIT;
}
pContext->hevReadyForNotifications = CreateEvent(NULL, TRUE, TRUE, NULL);
if (pContext->hevReadyForNotifications == NULL) {
dwErr = GetLastError();
DEBUGMSG(ZONE_ERROR, (_T("%s Failed to create event. Error = %d\r\n"),
pszFname, dwErr));
goto EXIT;
}
// Open the device key
pContext->hKey = OpenDeviceKey(pszContext);
if (pContext->hKey == NULL) {
dwErr = GetLastError();
DEBUGMSG(ZONE_ERROR, (_T("%s Failed to open device key \"%s\". Error = %d\r\n"),
pszFname, pszContext, dwErr));
goto EXIT;
}
pContext->pUfnBus = new CUfnBus(pszContext, pContext);
if ( (pContext->pUfnBus == NULL) || (!pContext->pUfnBus->Init()) ) {
goto EXIT;
}
// Initialize the PDD
dwErr = UfnPdd_Init(pszContext, pContext, &MddInterfaceInfo, &pContext->PddInfo);
if (dwErr != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ERROR, (_T("%s PDD initialization failed.\r\n"), pszFname));
goto EXIT;
}
if (IsPddInterfaceInfoValid(&pContext->PddInfo)) {
DEBUGMSG(ZONE_INIT, (_T("%s PDD has %u endpoints\r\n"), pszFname,
pContext->PddInfo.dwEndpointCount));
DEBUGMSG(ZONE_INIT, (_T("%s PDD supports speeds 0x%x\r\n"), pszFname,
pContext->PddInfo.dwCapabilities));
pContext->fPddInitialized = TRUE;
}
else {
RETAILMSG(1, (_T("%s PDD interface info is invalid.\r\n"),
pszFname));
// Try to call PDD's deinit.
if (pContext->PddInfo.pfnDeinit) {
pContext->PddInfo.pfnDeinit(pContext->PddInfo.pvPddContext);
}
}
EXIT:
if (pContext && !pContext->fPddInitialized) {
// Failed to initialize. Free resources.
FreeContext(pContext);
pContext = NULL;
}
FUNCTION_LEAVE_MSG();
return (DWORD) pContext;
}
extern "C"
BOOL
UFN_PreDeinit (
DWORD dwContext
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DWORD dwRet = ERROR_SUCCESS;
PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) dwContext;
VERIFY_PCONTEXT();
ValidateContext(pContext);
pContext->pOpenList->PreDeinit(UFN_PreClose);
EXIT:
FUNCTION_LEAVE_MSG();
return (dwRet == ERROR_SUCCESS);
}
// Deinitialize the client, PDD, and MDD.
extern "C"
BOOL
UFN_Deinit (
DWORD dwContext
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DWORD dwRet = ERROR_SUCCESS;
PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) dwContext;
VERIFY_PCONTEXT();
ValidateContext(pContext);
pContext->pOpenList->Deinit(UFN_Close);
FreeContext(pContext);
EXIT:
FUNCTION_LEAVE_MSG();
return (dwRet == ERROR_SUCCESS);
}
static
VOID
ValidateBusContext(
PUFN_MDD_BUS_OPEN_CONTEXT pBusContext
)
{
PREFAST_DEBUGCHK(pBusContext);
DEBUGCHK(pBusContext->dwSig == UFN_MDD_BUS_SIG);
DEBUGCHK(pBusContext->pMddContext);
ValidateContext(pBusContext->pMddContext);
DEBUGCHK(pBusContext->hkClients);
}
extern "C"
DWORD
UFN_Open (
DWORD dwContext,
DWORD dwAccessMode,
DWORD dwShareMode
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DWORD dwRet;
PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) dwContext;
DEBUGCHK(IS_VALID_MDD_CONTEXT(pContext));
if (dwAccessMode & DEVACCESS_BUSNAMESPACE) {
// This is a bus access
PUFN_MDD_BUS_OPEN_CONTEXT pBusContext = (PUFN_MDD_BUS_OPEN_CONTEXT)
LocalAlloc(LPTR, sizeof(UFN_MDD_BUS_OPEN_CONTEXT));
if (pBusContext) {
pBusContext->dwSig = UFN_MDD_BUS_SIG;
pBusContext->pMddContext = pContext;
DWORD dwErr = CUfnBus::OpenFunctionKey(&pBusContext->hkClients);
if (dwErr != ERROR_SUCCESS) {
LocalFree(pBusContext);
pBusContext = NULL;
}
}
if (pBusContext) {
ValidateBusContext(pBusContext);
if (!pContext->pOpenList->AddContext((DWORD) pBusContext)) {
LocalFree(pBusContext);
pBusContext = NULL;
}
}
dwRet = (DWORD) pBusContext;
}
else {
// Standard access
dwRet = (DWORD) pContext;
}
FUNCTION_LEAVE_MSG();
return dwRet;
}
extern "C"
BOOL
UFN_PreClose (
DWORD dwContext
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DWORD dwRet = ERROR_SUCCESS;
PUFN_MDD_CONTEXT_SIG pMddContextSig = (PUFN_MDD_CONTEXT_SIG) dwContext;
if (pMddContextSig == NULL) {
dwRet = ERROR_INVALID_HANDLE;
}
else if (pMddContextSig->dwSig == UFN_MDD_BUS_SIG) {
PUFN_MDD_BUS_OPEN_CONTEXT pBusContext =
(PUFN_MDD_BUS_OPEN_CONTEXT) pMddContextSig;
ValidateBusContext(pBusContext);
}
else if (pMddContextSig->dwSig == UFN_MDD_SIG) {
PUFN_MDD_CONTEXT pMddContext =
(PUFN_MDD_CONTEXT) pMddContextSig;
ValidateContext(pMddContext);
}
// No threads to release.
if (dwRet != ERROR_SUCCESS) {
SetLastError(dwRet);
}
FUNCTION_LEAVE_MSG();
return (dwRet == ERROR_SUCCESS);
}
extern "C"
BOOL
UFN_Close (
DWORD dwContext
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DWORD dwRet = ERROR_SUCCESS;
PUFN_MDD_CONTEXT_SIG pMddContextSig = (PUFN_MDD_CONTEXT_SIG) dwContext;
if (pMddContextSig == NULL) {
dwRet = ERROR_INVALID_HANDLE;
}
else if (pMddContextSig->dwSig == UFN_MDD_BUS_SIG) {
PUFN_MDD_BUS_OPEN_CONTEXT pBusContext =
(PUFN_MDD_BUS_OPEN_CONTEXT) pMddContextSig;
ValidateBusContext(pBusContext);
RegCloseKey(pBusContext->hkClients);
PUFN_MDD_CONTEXT pContext = pBusContext->pMddContext;
pContext->pOpenList->RemoveContext(dwContext);
LocalFree(pBusContext);
}
else if (pMddContextSig->dwSig == UFN_MDD_SIG) {
PUFN_MDD_CONTEXT pMddContext =
(PUFN_MDD_CONTEXT) pMddContextSig;
ValidateContext(pMddContext);
}
else {
DEBUGCHK(FALSE);
dwRet = ERROR_INVALID_HANDLE;
}
if (dwRet != ERROR_SUCCESS) {
SetLastError(dwRet);
}
FUNCTION_LEAVE_MSG();
return (dwRet == ERROR_SUCCESS);
}
// Pass power down request to the PDD.
extern "C"
void
UFN_PowerDown(
DWORD dwContext
)
{
PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) dwContext;
DEBUGCHK(IS_VALID_MDD_CONTEXT(pContext));
if (!pContext->pUfnBus->IsChildPowerManaged()) {
pContext->pUfnBus->SetChildDevicePowerState(D4);
}
pContext->PddInfo.pfnPowerDown(pContext->PddInfo.pvPddContext);
}
// Pass power up request to the PDD.
extern "C"
void
UFN_PowerUp(
DWORD dwContext
)
{
PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) dwContext;
DEBUGCHK(IS_VALID_MDD_CONTEXT(pContext));
pContext->PddInfo.pfnPowerUp(pContext->PddInfo.pvPddContext);
if (!pContext->pUfnBus->IsChildPowerManaged()) {
pContext->pUfnBus->SetChildDevicePowerState(D0);
}
}
DWORD
GetClientFunctions(
PUFN_FUNCTIONS pUfnFunctions
)
{
SETFNAME();
PREFAST_DEBUGCHK(pUfnFunctions);
DWORD dwRet = ERROR_SUCCESS;
pUfnFunctions->lpRegisterDevice = &UfnMdd_RegisterDevice;
pUfnFunctions->lpStart = &UfnMdd_Start;
pUfnFunctions->lpStop = &UfnMdd_Stop;
pUfnFunctions->lpDeregisterDevice = &UfnMdd_DeregisterDevice;
pUfnFunctions->lpOpenPipe = &UfnMdd_OpenPipe;
pUfnFunctions->lpClosePipe = &UfnMdd_ClosePipe;
pUfnFunctions->lpIssueTransfer = &UfnMdd_IssueTransfer;
pUfnFunctions->lpGetTransferStatus = &UfnMdd_GetTransferStatus;
pUfnFunctions->lpAbortTransfer = &UfnMdd_AbortTransfer;
pUfnFunctions->lpCloseTransfer = &UfnMdd_CloseTransfer;
pUfnFunctions->lpStallPipe = &UfnMdd_StallPipe;
pUfnFunctions->lpClearPipeStall = &UfnMdd_ClearPipeStall;
pUfnFunctions->lpInitiateRemoteWakeup = &UfnMdd_InitiateRemoteWakeup;
pUfnFunctions->lpSendControlStatusHandshake = &UfnMdd_SendControlStatusHandshake;
return dwRet;
}
// IOCTLs with a Function value between 0x200 and 0x2FF are reserved
// for the OEM and the PDD.
extern "C"
BOOL
UFN_IOControl (
DWORD dwContext,
DWORD dwCode,
PBYTE pbInBuf,
DWORD cbInBuf,
PBYTE pbOutBuf,
DWORD cbOutBuf,
PDWORD pcbActualOutBuf
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
BOOL fRet = FALSE;
PUFN_MDD_CONTEXT_SIG pMddContextSig = (PUFN_MDD_CONTEXT_SIG) dwContext;
if (pMddContextSig == NULL) {
SetLastError(ERROR_INVALID_HANDLE);
}
else if (pMddContextSig->dwSig == UFN_MDD_BUS_SIG) {
PUFN_MDD_BUS_OPEN_CONTEXT pBusContext =
(PUFN_MDD_BUS_OPEN_CONTEXT) pMddContextSig;
ValidateBusContext(pB
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -