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

📄 enum.cpp

📁 It permits simultaneous use of multiple USB Serial protocols.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    
    ValidateContext(pContext);

    CONTROL_RESPONSE (*pfnProcess)(PUFN_MDD_CONTEXT, USB_DEVICE_REQUEST, DWORD) = NULL;
    
    // Process device-to-host requests
    if ( udr.bmRequestType == 
         (USB_REQUEST_DEVICE_TO_HOST | USB_REQUEST_STANDARD | USB_REQUEST_FOR_DEVICE) ) {
        // Process device requests
        switch (udr.bRequest) {
            case USB_REQUEST_GET_DESCRIPTOR:
                pfnProcess = &ProcessGetDescriptor;
                break;
            case USB_REQUEST_GET_CONFIGURATION:
                pfnProcess = &ProcessGetConfiguration;
                break;
            case USB_REQUEST_GET_STATUS:
                pfnProcess = &ProcessGetStatus;
                break;
        }
    }
    else if ( udr.bmRequestType == 
        (USB_REQUEST_DEVICE_TO_HOST | USB_REQUEST_STANDARD | USB_REQUEST_FOR_INTERFACE) ) {
        // Process interface requests
        switch (udr.bRequest) {
            case USB_REQUEST_GET_INTERFACE:
                pfnProcess = &ProcessGetInterface;
                break;
            case USB_REQUEST_GET_STATUS:
                pfnProcess = &ProcessGetStatus;
                break;
        }
    }
    else if ( udr.bmRequestType == 
        (USB_REQUEST_DEVICE_TO_HOST | USB_REQUEST_STANDARD | USB_REQUEST_FOR_ENDPOINT) ) {
        // Process interface requests
        switch (udr.bRequest) {
            case USB_REQUEST_GET_STATUS:
                pfnProcess = &ProcessGetStatus;
                break;
        }
    }    
    // Process host-to-device requests
    else if ( udr.bmRequestType == 
        (USB_REQUEST_HOST_TO_DEVICE | USB_REQUEST_STANDARD | USB_REQUEST_FOR_DEVICE) ) {
        switch (udr.bRequest) {            
            case USB_REQUEST_SET_ADDRESS:
                pfnProcess = &ProcessSetAddress;
                break;

            case USB_REQUEST_SET_CONFIGURATION:
                pfnProcess = &ProcessSetConfiguration;
                break;
            case USB_REQUEST_CLEAR_FEATURE:
                pfnProcess = &ProcessClearFeature;
                break;
                
            case USB_REQUEST_SET_FEATURE:
                pfnProcess = &ProcessSetFeature;
                break;
        }
    }
    else if ( udr.bmRequestType == 
        (USB_REQUEST_HOST_TO_DEVICE | USB_REQUEST_STANDARD | USB_REQUEST_FOR_INTERFACE) ) {
        switch (udr.bRequest) {
            case USB_REQUEST_SET_INTERFACE:
                pfnProcess = &ProcessSetInterface;
                break;
        }
    }
    else if ( udr.bmRequestType == 
        (USB_REQUEST_HOST_TO_DEVICE | USB_REQUEST_STANDARD | USB_REQUEST_FOR_ENDPOINT) ) {
        switch (udr.bRequest) {
            case USB_REQUEST_CLEAR_FEATURE:
                pfnProcess = &ProcessClearFeature;
                break;
                
            case USB_REQUEST_SET_FEATURE:
                pfnProcess = &ProcessSetFeature;
                break;
        }
    }

    CONTROL_RESPONSE response;
    if (pfnProcess) {
        response = pfnProcess(pContext, udr, dwMsg);
    }
    else {
        response = CR_UNHANDLED_REQUEST;
    }
    
    FUNCTION_LEAVE_MSG();

    return response;
}


static
VOID
CloseAllPipesExceptEndpointZero(
    PUFN_MDD_CONTEXT pContext 
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    ValidateContext(pContext);
    PREFAST_DEBUGCHK(pContext->pPipes);

    // Don't close endpoint 0.
    for (DWORD dwPipe = 1; dwPipe < pContext->PddInfo.dwEndpointCount; ++dwPipe) {
        PCPipe pPipe = &pContext->pPipes[dwPipe];
        if (pPipe->IsOpen()) {
            pPipe->Close();
        }
    }

    FUNCTION_LEAVE_MSG();
}


// Performs the check to see if we are ready for a notification.
static
inline
BOOL
IgnoreNotificationCheck(
    PUFN_MDD_CONTEXT pContext
    )
{
    return (!pContext->pUfnBus->IsClientActive() || pContext->fClientIsBeingAddedOrRemoved);
}


// Ignore this notification because we are not ready for it?
static
BOOL
IgnoreNotification(
    PUFN_MDD_CONTEXT pContext,
    DWORD dwMsg,
    DWORD dwParam
    )
{
    BOOL fIgnore = IgnoreNotificationCheck(pContext);
    if (fIgnore) {
        // We may not be ready to receive notifications--perhaps we
        // are in the process of loading the client driver. Verify
        // that we are ready and then check the other flags again.
        WaitForSingleObject(pContext->hevReadyForNotifications, READY_FOR_NOTIFICATIONS_TIMEOUT);
        fIgnore = IgnoreNotificationCheck(pContext);
    }

    if (fIgnore == FALSE) {
        // Ignore notifications when detached
        if ( (pContext->deviceState == DS_DETACHED) &&
              (dwMsg != UFN_MSG_BUS_EVENTS || dwParam != UFN_ATTACH) ) {
            fIgnore = TRUE;
        }
    }
    
    return fIgnore;
}


// Notification routine for the device.
BOOL 
WINAPI 
UfnMdd_Notify(
    PVOID pvNotifyParameter,
    DWORD dwMsg,
    DWORD dwParam
    )
{   
    SETFNAME();

    PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) pvNotifyParameter;
    ValidateContext(pContext);

    FUNCTION_ENTER_MSG();

    BOOL fRet = FALSE;
    CONTROL_RESPONSE response = CR_SUCCESS;
    BOOL fSendNotificationToClient = TRUE;
    BOOL fEnteredCs = FALSE;

    if (dwMsg == UFN_MSG_TRANSFER_COMPLETE) {
        PSTransfer pPddTransfer = (PSTransfer) dwParam;
        PCUfnMddTransfer pTransfer = CUfnMddTransfer::ConvertFromPddTransfer(pPddTransfer);
        DWORD dwErr = CUfnMddTransfer::ReferenceTransferHandle(pTransfer);
        if (dwErr == ERROR_SUCCESS) {
            DEBUGCHK(pTransfer->IsInPdd());
            pTransfer->LeavingPdd();
        
            PCPipe pPipe = pTransfer->GetPipe();
            dwErr = pPipe->TransferComplete(pTransfer, TRUE);
            pTransfer->Release();
            fRet = TRUE;
        }
        else {
            DEBUGMSG(ZONE_ERROR, (_T("%s PDD passed a bad transfer\r\n"),
                pszFname));
        }

        goto EXIT;
    }

    if (IgnoreNotification(pContext, dwMsg, dwParam)) {
        // Are we receiving a notification before the client is fully initialized?
        // If so try adding a sleep to the PDD's IST before enabling interrupts.
        RETAILMSG(1, (_T("%s Ignoring notification 0x%08x - 0x%08x from PDD\r\n"),
            pszFname, dwMsg, dwParam));
        goto EXIT;
    }

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

    PCPipe pPipeZero = &pContext->pPipes[0];

    switch(dwMsg) {
        case UFN_MSG_BUS_EVENTS: {
            DEVICE_STATE dsNew;
            BOOL fChangeState = TRUE;
            
            switch (dwParam) {
            case UFN_DETACH:
                DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Detached\r\n"), pszFname));                
                if (pContext->deviceState == DS_DETACHED) {
                    DEBUGMSG(ZONE_WARNING, (_T("%s Received detach when already detached!\r\n"),
                        pszFname));
                    fChangeState = FALSE;
                }
                else {
                    dsNew = DS_DETACHED;
                }
                // Free resources associated with free transfers
                pContext->pFreeTransferList->Compact();
                break;

            case UFN_ATTACH:
                DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Attached\r\n"), pszFname));
                if (pContext->deviceState == DS_ATTACHED) {
                    DEBUGMSG(ZONE_WARNING, (_T("%s Received attach when already attached!\r\n"),
                        pszFname));
                    fChangeState = FALSE;
                }
                else {                
                    dsNew = DS_ATTACHED;
                    pContext->Speed = BS_UNKNOWN_SPEED;
                    pContext->fRemoteWakeupEnabled = FALSE;
                }
                break;
            
            case UFN_RESET:
                DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Root port reset\r\n"), pszFname));
                if (pContext->deviceState == DS_DETACHED) {
                    DEBUGMSG(ZONE_WARNING, (_T("%s Received reset when detached!\r\n"),
                        pszFname));
                    fChangeState = FALSE;
                }
                else {
                    dsNew = DS_DEFAULT;
                    pContext->dwConfiguration = 0;
                    pContext->fRemoteWakeupEnabled = FALSE;
                }
                if (pContext->hParentBusHandle != NULL ) {
                    BusChildIoControl(pContext->hParentBusHandle,IOCTL_BUS_USBOTG_HNP_DISABLE,NULL,0);
                }
                break;
                
            case UFN_SUSPEND:
                DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Suspended\r\n"), pszFname));
                DEBUGCHK(pContext->deviceState != DS_DETACHED);
                pContext->deviceStatePriorToSuspend = pContext->deviceState;
                dsNew = DS_SUSPENDED;
                // Need to call bus driver to indicate bus suspend.
                if (pContext->hParentBusHandle != NULL ) {
                    BusChildIoControl(pContext->hParentBusHandle,IOCTL_BUS_USBOTG_SUSPEND,NULL,0);
                }
                break;

            case UFN_RESUME:
                DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Resumed\r\n"), pszFname));
                DEBUGCHK(pContext->deviceState != DS_DETACHED);
                dsNew = pContext->deviceStatePriorToSuspend;
                // Need to call bus driver to indicate bus suspend.
                if (pContext->hParentBusHandle != NULL ) {
                    BusChildIoControl(pContext->hParentBusHandle,IOCTL_BUS_USBOTG_RESUME,NULL,0);
                }
                break;

            default:
                DEBUGCHK(FALSE); // What message is this?
                dsNew = pContext->deviceState;
            }

            if (fChangeState) {
                ChangeDeviceState(pContext, dsNew);
                CloseAllPipesExceptEndpointZero(pContext);
                pPipeZero->AbortAllTransfers();
            }
            else {
                fSendNotificationToClient = FALSE;
            }

            break;
        }

        case UFN_MSG_BUS_SPEED:
            DEBUGCHK( (dwParam == BS_HIGH_SPEED) || (dwParam == BS_FULL_SPEED) );
            DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Attached to %s speed bus.\r\n"),
                pszFname, (dwParam == BS_HIGH_SPEED ? _T("high") : _T("full") )));
            
            DEBUGCHK(pContext->deviceState != DS_DETACHED);            
            DEBUGCHK((pContext->PddInfo.dwCapabilities & dwParam) != 0);
            pContext->Speed = (UFN_BUS_SPEED) dwParam;
            break;

        case UFN_MSG_SETUP_PACKET:
        case UFN_MSG_PREPROCESSED_SETUP_PACKET: {
            PUSB_DEVICE_REQUEST pUdr = (PUSB_DEVICE_REQUEST) dwParam;
            
            PREFAST_DEBUGCHK(pUdr);
            DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Received %s setup packet: %02x %02x %04x %04x %04x\r\n"),
                pszFname, (dwMsg == UFN_MSG_SETUP_PACKET ? _T("") : _T("preprocessed")),
                pUdr->bmRequestType, pUdr->bRequest, pUdr->wValue,
                pUdr->wIndex, pUdr->wLength));
            DEBUGCHK(pContext->deviceState != DS_DETACHED);
            
            response = ProcessRequest(pContext, *pUdr, dwMsg);

            if (dwMsg == UFN_MSG_SETUP_PACKET) {
                if (response == CR_UNHANDLED_REQUEST) {
                    DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Unhandled setup packet. Passing it to client\r\n"),
                        pszFname));
                }
                else {                
                    dwMsg = UFN_MSG_PREPROCESSED_SETUP_PACKET;
                }
            }
            
            break;
        }

        case UFN_MSG_SET_ADDRESS: {
            // Some controllers automatically handle set address so they must
            // tell us when the device has been addressed.
            DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Set address (%u).\r\n"), 
                pszFname, dwParam));
            DEBUGCHK(pContext->deviceState != DS_DETACHED);
            DEBUGCHK(pContext->deviceState != DS_CONFIGURED);
            DEVICE_STATE ds;
            
            if (dwParam == 0) {
                ds = DS_DEFAULT;
            }
            else {
                ds = DS_ADDRESSED;
            }

            ChangeDeviceState(pContext, ds);
            break;
        }

        case UFN_MSG_CONFIGURED: {
            // Some controllers automatically handle set address so they must
            // tell us when the device has been addressed.
            DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Set configuration (%u).\r\n"), 
                pszFname, dwParam));
            DEBUGCHK(pContext->deviceState != DS_DETACHED);
            
            if (dwParam == 0) {
                ChangeDeviceState(pContext, DS_ADDRESSED);
            }
            else {
                DEBUGCHK(pContext->deviceState == DS_ADDRESSED);
                ChangeDeviceState(pContext, DS_CONFIGURED);
            }            
            break;
        }

        default:
            DEBUGCHK(FALSE); // What is this message?
    }

    if (fSendNotificationToClient) {
        fRet = SendDeviceNotification(pContext->lpDeviceNotify, 
            pContext->pvDeviceNotifyParameter, dwMsg, dwParam);
    }

    if (response == CR_STALL_DEFAULT_PIPE) {
        pPipeZero->Stall();
        pPipeZero->SendControlStatusHandshake();
    }
    else if (response == CR_SUCCESS_SEND_CONTROL_HANDSHAKE) {
        pPipeZero->SendControlStatusHandshake();
    }

EXIT:
    FUNCTION_LEAVE_MSG();
    if (fEnteredCs) {
        LeaveCriticalSection(&pContext->csMddAccess);
    }

    return fRet;
}

⌨️ 快捷键说明

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