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

📄 cbit.c

📁 Windows CE 5.0下的U盘驱动源代码。
💻 C
📖 第 1 页 / 共 2 页
字号:
            dwErr = ERROR_GEN_FAILURE;
        }
    }

    STOP_DT( TEXT("CBIT_CommandTransport"), 1000, pUsbDevice->Timeouts.CommandBlock );
    
    DEBUGMSG( ZONE_TRACE, (TEXT("USBMSC<CBIT_CommandTransport:%d\n"), dwErr) );

    return dwErr;
}


DWORD
CBIT_StatusTransport(
    PUSBMSC_DEVICE     pUsbDevice
    )
{
    DWORD dwBytesTransferred = 0;   
    DWORD dwErr = ERROR_SUCCESS;
    DWORD dwUsbErr = USB_NO_ERROR;

    UCHAR  ucStatus[2];
    DWORD  dwStatusSize = sizeof(ucStatus);
    
    BOOL  bRc = FALSE;

    if ( !ACCEPT_IO(pUsbDevice) ) {
        dwErr = ERROR_ACCESS_DENIED;
        DEBUGMSG( ZONE_ERR,(TEXT("CBIT_StatusTransport error:%d\n"), dwErr));
        SetLastError(dwErr);
        return dwErr;
    }

    if (pUsbDevice->Interrupt.hPipe && !pUsbDevice->Flags.IgnoreInterrupt) {

        memset( ucStatus, 0, dwStatusSize );

        START_DT;

        dwErr = IssueInterruptTransfer(pUsbDevice->UsbFuncs,
                                       pUsbDevice->Interrupt.hPipe,
                                       DefaultTransferComplete,
                                       pUsbDevice->Interrupt.hEvent,
                                       USB_IN_TRANSFER|USB_NO_WAIT|USB_SHORT_TRANSFER_OK,
                                       ucStatus, 0,
                                       dwStatusSize,
                                       &dwBytesTransferred,
                                       pUsbDevice->Timeouts.CommandStatus,
                                       &dwUsbErr );

        STOP_DT( TEXT("StatusTransport"), 100, pUsbDevice->Timeouts.CommandStatus );

        // check Status Transport bits
        if ( ERROR_SUCCESS != dwErr || USB_NO_ERROR != dwUsbErr || dwBytesTransferred != dwStatusSize ) {

            ResetPipe(pUsbDevice->UsbFuncs, pUsbDevice->Interrupt.hPipe, USB_NO_WAIT);

            pUsbDevice->InterruptErrors++;

            DEBUGMSG( ZONE_ERR, (TEXT("CBIT_Status Transport error(%d, 0x%x, %d, %d)\n"), dwErr, dwUsbErr, dwBytesTransferred, pUsbDevice->InterruptErrors ));

            goto CBIT_StatusTransportDone;
        
        } else {
            
            pUsbDevice->InterruptErrors = 0;

        }

        //
        // Check Command Status
        //
        switch (pUsbDevice->pUsbInterface->Descriptor.bInterfaceSubClass)
        {
            case USBMSC_SUBCLASS_UFI:
                //
                // The ASC & (optional) ASCQ are in the data block.
                //
                if ( ucStatus[0] ) {
                    DEBUGMSG(ZONE_ERR, (TEXT("CBIT_StatusTransport::UFI: ASC:0x%x ASCQ:0x%x\n"), ucStatus[0], ucStatus[1] ));
                    dwErr = ERROR_PERSISTANT;
                }
                break;

            default: 
            {
                if (CBIT_COMMAND_COMPLETION_INTERRUPT != ucStatus[0] ) {
            
                    DEBUGMSG(ZONE_ERR, (TEXT("Invalid Command Completion Interrupt: 0x%x\n"), ucStatus[0] ));

                    TEST_TRAP();
            
                    if (ERROR_SUCCESS == dwErr)
                        dwErr = ERROR_GEN_FAILURE;
        
                    goto CBIT_StatusTransportDone;
                }

                switch ( ucStatus[1] & 0x0F ) {

                    case CBIT_STATUS_SUCCESS:
                    break;

                    case CBIT_STATUS_FAIL:
                        DEBUGMSG(ZONE_ERR, (TEXT("CBIT_STATUS_FAIL\n")));
                        dwErr = ERROR_GEN_FAILURE;
                    break;

                    case CBIT_STATUS_PHASE_ERROR:
                        DEBUGMSG(ZONE_ERR, (TEXT("CBIT_STATUS_PHASE_ERROR\n")));
                        // TBD: send CommandBlockReset
                        dwErr = ERROR_GEN_FAILURE;
                    break;

                    case CBIT_STATUS_PERSISTENT_ERROR:
                        DEBUGMSG(ZONE_ERR, (TEXT("CBIT_STATUS_PERSISTENT_ERROR\n")));
                        //
                        // The CBIT spec states that a REQUEST_SENSE command block must be sent,
                        // which must be handled by the disk device.
                        //
                        dwErr = ERROR_PERSISTANT;
                        TEST_TRAP();
                    break;

                    default:
                        TEST_TRAP();
                        DEBUGMSG(ZONE_ERR, (TEXT("Invalid Command Completion Status: 0x%x\n"), ucStatus[1] ));
                        dwErr = ERROR_GEN_FAILURE;
                    break;
                }
            }
        }
    }

CBIT_StatusTransportDone:
    //
    // TODO: Some devices claim to use the interrupt endpoint but really do not.
    // Currently, the only way to determine if the device really uses the
    // interrupt endpoint is to try it a few times and see. Need to add registry work arounds.
    // Exceptions:
    //  UFI Spec 2.1: Interrupt endpoint required
    //
    if (MAX_INT_RETRIES == pUsbDevice->InterruptErrors &&
        !(USBMSC_SUBCLASS_UFI == pUsbDevice->pUsbInterface->Descriptor.bInterfaceSubClass && 
          USBMSC_INTERFACE_PROTOCOL_CBIT == pUsbDevice->pUsbInterface->Descriptor.bInterfaceProtocol)
        )
    {
        DEBUGMSG( ZONE_WARN, (TEXT("USBMSC:IgnoreInterrupt:ON\n"), dwErr) );
        EnterCriticalSection(&pUsbDevice->Lock);
        pUsbDevice->Flags.IgnoreInterrupt = TRUE;        
        LeaveCriticalSection(&pUsbDevice->Lock);
        pUsbDevice->InterruptErrors++;
    }
    
    DEBUGMSG( ZONE_TRACE, (TEXT("USBMSC<CBIT_StatusTransport:%d\n"), dwErr) );
    
    return dwErr;
}


//
// Command/Data/Status Transport 
//
DWORD
CBIT_DataTransfer(
    PUSBMSC_DEVICE           pUsbDevice,
    PTRANSPORT_COMMAND       pCommand,
    OPTIONAL PTRANSPORT_DATA pData,    // OPTIONAL
    BOOL                     Direction // TRUE = Data-In, else Data-Out
    )
{
    DWORD dwBytesTransferred = 0;   
    DWORD dwErr = ERROR_SUCCESS;
    DWORD dwUsbErr = USB_NO_ERROR;
    DWORD dwResetErr, dwStatusErr;

    BOOL  bRc = FALSE;

    INIT_DT;

    DEBUGMSG(ZONE_TRACE,(TEXT("USBMSC>CBIT_DataTransfer\n")));

    // parameter checks
    if ( !pCommand || !pCommand->CommandBlock /*|| pCommand->Length > MAX_CBWCB_SIZE*/ ) {
        dwErr = ERROR_INVALID_PARAMETER;
        DEBUGMSG(ZONE_ERR,(TEXT("CBIT_DataTransfer error:%d\n"),dwErr));
        SetLastError(dwErr);
        return dwErr;
    }

    if ( !ACCEPT_IO(pUsbDevice) ) {
        dwErr = ERROR_ACCESS_DENIED;
        DEBUGMSG( ZONE_ERR,(TEXT("CBIT_DataTransfer error:%d\n"), dwErr));
        SetLastError(dwErr);
        return dwErr;
    }

    //
    // We require exclusive entry into the transport.
    // we could implement command queuing.
    //
    EnterCriticalSection(&pUsbDevice->Lock);

    if ( !CBIT_ResetAllPipes(pUsbDevice) ) {
        DEBUGMSG( ZONE_ERR, (TEXT("CBIT_ResetAllPipes failed!\n")));
        dwErr = ERROR_GEN_FAILURE;
        goto CBIT_SendCommandDone;
    }

    //
    // Command Block Transport via ADSC
    //
    dwErr = CBIT_CommandTransport( pUsbDevice,
                                   pCommand,
                                   &dwBytesTransferred );

    if (ERROR_SUCCESS != dwErr || dwBytesTransferred != pCommand->Length) {
        // 2.3.2.1: if the device does STALL an ADSC, then the device shall not
        // transport the status for the command block by interrupt pipe.
        // Treat a timeout in the same manner.
        goto CBIT_SendCommandDone;
    }

    //
    // (optional) Data Transport
    //
    if (pData && pData->DataBlock && pData->RequestLength) {
        UCHAR resets = 0; // consecutive resets
        DEBUGMSG(ZONE_BOT,(TEXT("Data%s Transport - dwDataLength:%d, TimeOut:%d \n"), Direction ? TEXT("In") : TEXT("Out"),  pData->RequestLength, pCommand->Timeout ));
        while (resets < 3) {
            PIPE pipeObj = Direction ? pUsbDevice->BulkIn : pUsbDevice->BulkOut;
            DWORD dwFlags = Direction ? (USB_IN_TRANSFER|USB_NO_WAIT|USB_SHORT_TRANSFER_OK) : (USB_OUT_TRANSFER|USB_NO_WAIT|USB_SHORT_TRANSFER_OK);
            BOOL fRet ;
            DWORD dwTimeout = pCommand->Timeout;
            DWORD dwStartTime=0;
            DWORD dwUsbErr = USB_NOT_COMPLETE_ERROR;
            DWORD dwTransferLength = 0 ;
            ResetEvent(pipeObj.hEvent);
            
            fRet = BulkTransferMgrTransfer(pipeObj.pAsyncContent, DefaultTransferComplete, pipeObj.hEvent, 
                dwFlags, pData->DataBlock, pData->RequestLength );
            if (fRet ) {
                if (!BulkTransferWait(pipeObj.pAsyncContent, dwTimeout)) {
                    fRet = BulkTransferMgrGetStatus(pipeObj.pAsyncContent, &dwTransferLength , &dwUsbErr);
                    dwUsbErr = USB_NOT_COMPLETE_ERROR;
                }
                else {
                    fRet = BulkTransferMgrGetStatus(pipeObj.pAsyncContent, &dwTransferLength , &dwUsbErr);
                }
                BulkTransferClose(pipeObj.pAsyncContent);
            }
            pData->TransferLength  = dwTransferLength;
            
            DEBUGMSG( ZONE_WARN && pData->RequestLength!= pData->TransferLength, 
                (TEXT("CBIT_DataTransfer warning(a, RequestLength:%d TransferLength:%d Err:%d UsbErr:0x%x)\n"), pData->RequestLength, pData->TransferLength, dwErr, dwUsbErr ));
            if (USB_NO_ERROR != dwUsbErr) {
                //
                // reset the Bulk pipe
                //
                UCHAR bIndex = Direction ? pUsbDevice->BulkIn.bIndex : pUsbDevice->BulkOut.bIndex;
                
                DEBUGMSG( ZONE_ERR, (TEXT("CBIT_DataTransfer error(b, dwErr:%d, dwUsbErr:0x%x, dwTimeout:%d)\n"), dwErr, dwUsbErr, dwTimeout));

                resets++;

                dwResetErr = ResetBulkEndpoint( pUsbDevice->UsbFuncs,
                                                pUsbDevice->hUsbDevice,
                                                Direction ? pUsbDevice->BulkIn.hPipe : pUsbDevice->BulkOut.hPipe,
                                                DefaultTransferComplete,
                                                Direction ? pUsbDevice->BulkIn.hEvent : pUsbDevice->BulkOut.hEvent,
                                                bIndex,
                                                pUsbDevice->Timeouts.Reset );

                if (ERROR_SUCCESS != dwResetErr) {
                    DEBUGMSG( ZONE_ERR, (TEXT("ResetBulkEndpoint.1 ERROR:%d\n"), dwResetErr));
                    dwErr = ERROR_GEN_FAILURE;
                    break;
                }
                if (dwUsbErr == USB_NOT_COMPLETE_ERROR) { // Not be able complete. It is not stall.
                    dwErr = ERROR_GEN_FAILURE;
                    break;
                }
            }
            else { // Success.
                break;
            }
        }
    }


CBIT_SendCommandDone:
    //
    // cleanup        
    //
    if (ERROR_SUCCESS != dwErr) {
        bRc = CBIT_ResetRecovery(pUsbDevice);
    }
    else {
        //
        // Status Transport
        //
        DEBUGMSG(ZONE_BOT,(TEXT("Status Transport\n")));
        
        dwStatusErr = CBIT_StatusTransport( pUsbDevice );
        
        if (ERROR_SUCCESS != dwStatusErr ) {
            
            if (ERROR_SUCCESS == dwErr)
                dwErr = dwStatusErr;
        }

    }

    LeaveCriticalSection(&pUsbDevice->Lock);
   
    DEBUGMSG(ZONE_TRACE,(TEXT("USBMSC<CBIT_DataTransfer:%d\n"), dwErr));    

    return dwErr;
}

// EOF

⌨️ 快捷键说明

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