⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ufnmdd.cpp

📁 freescale i.mx31 BSP CE5.0全部源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
                pPipe->Reserve(Speed, TRUE, pInterface->Descriptor.bInterfaceNumber,
                    dwEndpoint, &pEndpoint->Descriptor);
                break;
            }
        }

        if (dwPipe == pContext->PddInfo.dwEndpointCount) {
            DEBUGMSG(ZONE_ERROR, (_T("%s Endpoint descriptor 0x%x cannot be supported\r\n"),
                pszFname, dwEndpoint));
            dwRet = ERROR_INVALID_PARAMETER;
            goto EXIT;
        }
    }

    dwRet = ERROR_SUCCESS;

EXIT:
    if (dwRet != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_ERROR, (_T("%s Cannot support provided %s speed interface\r\n"),
            pszFname, GetSpeedString(Speed)));
    }
    
    FUNCTION_LEAVE_MSG();

    return dwRet;
}


static
DWORD
IsDeviceSupportable(
    PUFN_MDD_CONTEXT pContext,
    UFN_BUS_SPEED Speed,
    PUSB_DEVICE_DESCRIPTOR pDeviceDesc,
    PUFN_CONFIGURATION pConfig
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    DWORD dwRet = ERROR_INVALID_PARAMETER;

    PREFAST_DEBUGCHK(pContext);
    PREFAST_DEBUGCHK(pDeviceDesc);
    PREFAST_DEBUGCHK(pConfig);
    DEBUGCHK(IS_VALID_SPEED(Speed));

    // Only support a client with one configuration
    if (pDeviceDesc->bNumConfigurations != 1) {
        DEBUGMSG(ZONE_ERROR, (_T("%s Only support one configuration\r\n"),
            pszFname));
        goto EXIT;
    }

    if ( (pConfig->Descriptor.bNumInterfaces == 0) || (pConfig->pInterfaces == NULL) ) {
        DEBUGMSG(ZONE_ERROR, (_T("%s No interface provided\r\n"), pszFname));
        goto EXIT;
    }

    // Make sure that the PDD can handle the configuration as a whole before giving it
    // each endpoint at a time.
    dwRet = pContext->PddInfo.pfnIsConfigurationSupportable(
        pContext->PddInfo.pvPddContext, Speed, pConfig);
    if (dwRet != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_ERROR, (_T("%s PDD cannot support the configuration\r\n"),
            pszFname));
        goto EXIT;
    }

    // Ensure that the specified endpoint 0 can be supported in both high 
    // and full speed modes.
    dwRet = IsEndpointZeroSupportable(pContext, pDeviceDesc, Speed);
    if (dwRet != ERROR_SUCCESS) {
        goto EXIT;
    }

    // Verify that the endpoints in every interface can be supported.
    DWORD cEndpoints;
    cEndpoints = 0;
    DWORD dwInterface;
    for (dwInterface = 0; dwInterface < pConfig->Descriptor.bNumInterfaces; ++dwInterface) {
        PUFN_INTERFACE pInterface = &pConfig->pInterfaces[dwInterface];
        cEndpoints += pInterface->Descriptor.bNumEndpoints;
        if (cEndpoints >= pContext->PddInfo.dwEndpointCount) {
            DEBUGMSG(ZONE_ERROR, (_T("%s Not enough endpoints for client\r\n"),
                pszFname));
            dwRet = ERROR_INVALID_PARAMETER;
            goto EXIT;
        }
        
        dwRet = IsInterfaceSupportable(pContext, pInterface, Speed, pConfig->Descriptor.bConfigurationValue);
        if (dwRet != ERROR_SUCCESS) {
            goto EXIT;
        }
    }

    // At this point, the device descriptors have been validated and 
    // adjusted with for endpoint 0.
    pContext->pPipes[0].Reserve(BS_FULL_SPEED, TRUE, 0, 0, NULL);
    pContext->pPipes[0].Reserve(BS_HIGH_SPEED, TRUE, 0, 0, NULL);

EXIT:
    FUNCTION_LEAVE_MSG();

    return dwRet;
}


static
VOID
AdjustDeviceDesc(
    PUFN_MDD_CONTEXT pContext,
    PUSB_DEVICE_DESCRIPTOR pDeviceDesc
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    PREFAST_DEBUGCHK(pContext);
    PREFAST_DEBUGCHK(pDeviceDesc);

    DWORD bcdUSB;
    DWORD dwErr = ReadRegDword(pContext->hKey, PSZ_REG_USB_RELEASE, FALSE, 
        &bcdUSB);
    if (dwErr == ERROR_SUCCESS) {
        DEBUGMSG(ZONE_FUNCTION, (_T("%s Using bcdUSB of 0x%04x\r\n"), 
            pszFname, bcdUSB));
        pDeviceDesc->bcdUSB = (WORD) bcdUSB;
    }
    
    FUNCTION_LEAVE_MSG();
}


// Register the descriptors with the MDD and PDD.
DWORD
WINAPI
UfnMdd_RegisterDevice(
    UFN_HANDLE              hDevice,
    PUSB_DEVICE_DESCRIPTOR  pHighSpeedDeviceDesc,
    PUFN_CONFIGURATION      pHighSpeedConfig,
    PUSB_DEVICE_DESCRIPTOR  pFullSpeedDeviceDesc,
    PUFN_CONFIGURATION      pFullSpeedConfig,
    PCUFN_STRING_SET        pStringSets,
    DWORD                   cStringSets
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    DWORD dwRet = ERROR_INVALID_PARAMETER;
    PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) hDevice;
    BOOL fTookCS = FALSE;
    
    VERIFY_PCONTEXT();

    EnterCriticalSection(&pContext->csMddAccess);
    fTookCS = TRUE;

    if ( (pHighSpeedDeviceDesc == NULL) || (pFullSpeedDeviceDesc == NULL) || 
         (pHighSpeedConfig == NULL) || (pFullSpeedConfig == NULL) ) {
        DEBUGMSG(ZONE_ERROR, (_T("%s Invalid parameter\r\n"), pszFname));
        goto EXIT;
    }

    if (pContext->fRunning) {
        // Must stop device before registering
        DEBUGMSG(ZONE_ERROR, (_T("%s Device is still running\r\n"), pszFname));
        dwRet = ERROR_BAD_ENVIRONMENT;
        goto EXIT;
    }

    if (pContext->fRegistered) {
        // Must deregister before re-registering
        DEBUGMSG(ZONE_ERROR, (_T("%s Device is still registered\r\n"), pszFname));
        dwRet = ERROR_BAD_ENVIRONMENT;
        goto EXIT;
    }

    __try {
        // Verify that the device and config descriptors are supportable.
        dwRet = IsDeviceSupportable(pContext, BS_FULL_SPEED, pFullSpeedDeviceDesc, 
            pFullSpeedConfig);
        if (dwRet != ERROR_SUCCESS) {
            goto EXIT;
        }
        
        if (PddSupportsHighSpeed(pContext)) {
            dwRet = IsDeviceSupportable(pContext, BS_HIGH_SPEED, pHighSpeedDeviceDesc, 
                pHighSpeedConfig);
            if (dwRet != ERROR_SUCCESS) {
                goto EXIT;
            }
        }

        // Adjust the full speed descriptor as necessary according to the registry
        AdjustDeviceDesc(pContext, pFullSpeedDeviceDesc);

        // Copy our structures.
        dwRet = CopyUsbStructs(pContext, pHighSpeedDeviceDesc, pHighSpeedConfig, 
            pFullSpeedDeviceDesc, pFullSpeedConfig, pStringSets, cStringSets);
        if (dwRet != ERROR_SUCCESS) {
            goto EXIT;
        }

        dwRet = pContext->PddInfo.pfnRegisterDevice(
            pContext->PddInfo.pvPddContext, 
            &pContext->HighSpeedDeviceDesc,
            &pContext->HighSpeedConfig,
            pContext->pHighSpeedConfigDesc,
            &pContext->FullSpeedDeviceDesc,
            &pContext->FullSpeedConfig,
            pContext->pFullSpeedConfigDesc,
            pContext->pStringSets,
            pContext->cStringSets
            );
        if (dwRet != ERROR_SUCCESS) {
            DEBUGMSG(ZONE_ERROR, (_T("%s Could not RegisterDevice with PDD\r\n"), pszFname));
            goto EXIT;
        }

        pContext->fRegistered = TRUE;
        DEBUGMSG(ZONE_INIT, (_T("%s Device registered\r\n"), pszFname));
        dwRet = ERROR_SUCCESS;
    } // __try
    __except(EXCEPTION_EXECUTE_HANDLER) {
        DEBUGMSG(ZONE_ERROR, (_T("%s Exception!\r\n"), pszFname));
        dwRet = ERROR_INVALID_PARAMETER;
    }

EXIT:    
    if (dwRet != ERROR_SUCCESS) {
        DEBUGCHK(pContext->fRegistered == FALSE);
        FreeUsbStructs(pContext);
        ResetPipeStatusTable(pContext);
    }

    FUNCTION_LEAVE_MSG();
    if (fTookCS) {
        LeaveCriticalSection(&pContext->csMddAccess);
    }

    return dwRet;
}


// Attach the device to the USB bus and register notification routines.
DWORD
WINAPI
UfnMdd_Start(
    UFN_HANDLE      hDevice,
    LPUFN_NOTIFY    lpDeviceNotify,
    PVOID           pvDeviceNotifyParameter,
    PUFN_PIPE       phDefaultPipe
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    DWORD dwRet;
    PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) hDevice;
    PCPipe pPipeZero = NULL;
    BOOL fTookCS = FALSE;
    
    VERIFY_PCONTEXT();

RETAILMSG(1,(TEXT("############# UfnMdd_Start: modified mx31 library ################\n\r")));
 
    EnterCriticalSection(&pContext->csMddAccess);
    fTookCS = TRUE;

    if (phDefaultPipe == NULL) {
        DEBUGMSG(ZONE_ERROR, (_T("%s Invalid parameter\r\n"), pszFname));
        dwRet = ERROR_INVALID_PARAMETER;
        goto EXIT;
    }

    if (!pContext->fRegistered) {
        DEBUGMSG(ZONE_ERROR, (_T("%s Device has not been registered\r\n"),
            pszFname)); 
        dwRet = ERROR_BAD_ENVIRONMENT;
        goto EXIT;
    }

    pContext->lpDeviceNotify = lpDeviceNotify;
    pContext->pvDeviceNotifyParameter = pvDeviceNotifyParameter;

    // For endpoint 0, transfer type and direction are ignored. Since
    // we do not know what speed bus this will be hooked up to, we use
    // the high speed endpoint 0 packet size.
    USB_ENDPOINT_DESCRIPTOR EndpointDesc;
    InitializeEndpointZeroDescriptor(pContext, 
        pContext->FullSpeedDeviceDesc.bMaxPacketSize0, &EndpointDesc);
    pPipeZero = &pContext->pPipes[0];
    dwRet = pPipeZero->Open(BS_FULL_SPEED, &EndpointDesc);
    if (dwRet != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_ERROR, (_T("%s Could not init endpoint 0\r\n"), pszFname));
        goto EXIT;
    }

    DEBUGCHK(pPipeZero->IsReserved(BS_FULL_SPEED));

    // Return handle to default pipe
    __try {
        *phDefaultPipe = pPipeZero;
    }
    __except(EXCEPTION_EXECUTE_HANDLER) {
        DEBUGMSG(ZONE_ERROR, (_T("%s Exception!\r\n"), pszFname));
        dwRet = ERROR_INVALID_PARAMETER;
    }

    pContext->pUfnBus->SetChildDevicePowerState(D0);

    dwRet = pContext->PddInfo.pfnStart(pContext->PddInfo.pvPddContext);
    if (dwRet != ERROR_SUCCESS) {
        goto EXIT;
    }
    
    DEBUGMSG(ZONE_INIT, (_T("%s Function controller running\r\n"), pszFname));
    
    pContext->fRunning = TRUE;
    
EXIT:
    if (dwRet != ERROR_SUCCESS) {
        if (IS_VALID_MDD_CONTEXT(pContext)) {
            if (pPipeZero && pPipeZero->IsOpen()) {
                pPipeZero->Close();
            }

            pContext->lpDeviceNotify = NULL;
            pContext->pvDeviceNotifyParameter = NULL;
        }
    }
    
    FUNCTION_LEAVE_MSG();
    if (fTookCS) {
        LeaveCriticalSection(&pContext->csMddAccess);
    }

    return dwRet;
}


DWORD
DoStop(
    PUFN_MDD_CONTEXT pContext
    )
{
    SETFNAME();

    EnterCriticalSection(&pContext->csMddAccess);
    FUNCTION_ENTER_MSG();

    // At this point, the client should not be able to receive notification callbacks 
    pContext->fRunning = FALSE;
    pContext->lpDeviceNotify = NULL;
    pContext->pvDeviceNotifyParameter = NULL;

    // Close all the pipes except for EP 0.
    for (DWORD dwPipe = 1; dwPipe < pContext->PddInfo.dwEndpointCount; ++dwPipe) {
        PCPipe pPipe = &pContext->pPipes[dwPipe];

        if (pPipe->IsOpen()) {
            VERIFY(pPipe->Close()); // Why would this fail?
        }
    }

    // Leave the critical section while calling PDD's Stop, since it will wait
    // for the IST to close, but the IST might be in the process of calling the
    // MDD's notification routine which also uses this critical section.
    LeaveCriticalSection(&pContext->csMddAccess);
    DWORD dwRet = pContext->PddInfo.pfnStop(pContext->PddInfo.pvPddContext);
    DEBUGCHK(dwRet == ERROR_SUCCESS); // Why would this fail?
    EnterCriticalSection(&pContext->csMddAccess);

    // Close endpoint 0.
    DEBUGCHK(pContext->pPipes[0].IsOpen());
    VERIFY(pContext->pPipes[0].Close()); // Why would this fail?

    pContext->pUfnBus->SetChildDevicePowerState(D4);

    FUNCTION_LEAVE_MSG();
    LeaveCriticalSection(&pContext->csMddAccess);

    return dwRet;
}


// Disconnect the device from the USB bus.
DWORD
WINAPI
UfnMdd_Stop(
    UFN_HANDLE hDevice
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    DWORD dwRet;
    PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) hDevice;
    
    VERIFY_PCONTEXT();
    VERIFY_RUNNING();
    dwRet = DoStop(pContext);

EXIT:
    FUNCTION_LEAVE_MSG();

    return dwRet;
}


DWORD
DoDeregisterDevice(
    PUFN_MDD_CONTEXT pContext
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();
    
    DWORD dwRet;
    
    if (pContext->fRunning) {
        // Must stop device before registering
        DEBUGMSG(ZONE_ERROR, (_T("%s Device is still running\r\n"), pszFname));
        dwRet = ERROR_BAD_ENVIRONMENT;
        goto EXIT;
    }

    if (pContext->fRegistered == FALSE) {
        // Must register before deregistering
        DEBUGMSG(ZONE_ERROR, (_T("%s Device is not registered\r\n"), pszFname));
        dwRet = ERROR_BAD_ENVIRONMENT;
        goto EXIT;
    }

    pContext->PddInfo.pfnDeregisterDevice(pContext->PddInfo.pvPddContext);

    FreeUsbStructs(pContext);
    ResetPipeStatusTable(pContext);

    pContext->fRegistered = FALSE;
    dwRet = ERROR_SUCCESS;

EXIT:
    FUNCTION_LEAVE_MSG();
    
    return dwRet;
}


// Clears the registered descriptors.
DWORD
WINAPI
UfnMdd_DeregisterDevice(
    UFN_HANDLE hDevice
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    DWORD dwRet;
    PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) hDevice;
    BOOL fTookCS = FALSE;
    
    VERIFY_PCONTEXT();
    EnterCriticalSection(&pContext->csMddAccess);
    fTookCS = TRUE;
    dwRet = DoDeregisterDevice(pContext);
    
EXIT:
    FUNCTION_LEAVE_MSG();
    if (fTookCS) {
        LeaveCriticalSection(&pContext->csMddAccess);
    }

    return dwRet;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -