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

📄 cbit.c

📁 PXA27X_CAYMAN BSP from CAYMAN board
💻 C
📖 第 1 页 / 共 2 页
字号:
    )
{
    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) 
    {
        const USHORT wMaxPacketSize = Direction ? pUsbDevice->BulkIn.wMaxPacketSize : pUsbDevice->BulkOut.wMaxPacketSize;
        // we don't provide our own phys buffer so are limited by USBD's max buffer size
        const DWORD  dwMaxBlock = (MAX_USB_BULK_LENGTH / wMaxPacketSize) * wMaxPacketSize;
        PVOID pDataBlock = pData->DataBlock;
        DWORD dwTransferLength = 0;
        DWORD dwRequestLength = 0;
        DWORD dwDataLength = pData->RequestLength;
        DWORD dwTimeout = pCommand->Timeout;
        DWORD dwStartTime=0;
        UCHAR resets = 0; // consecutive resets

        DEBUGMSG(ZONE_BOT,(TEXT("Data%s Transport - dwDataLength:%d, TimeOut:%d \n"), Direction ? TEXT("In") : TEXT("Out"), dwDataLength, dwTimeout ));

        while (dwDataLength && ((signed)dwTimeout > 0) && resets < 3)
        {
            dwRequestLength = min(dwMaxBlock, dwDataLength);
            dwTransferLength = 0;

            DEBUGMSG(ZONE_BOT,(TEXT("Data%s Transport - dwRequestLength:%d, TimeOut:%d \n"), Direction ? TEXT("In") : TEXT("Out"), dwRequestLength, dwTimeout ));

            ASSERT( dwRequestLength <= MAX_USB_BULK_LENGTH );

            dwStartTime = GetTickCount();

            dwErr = IssueBulkTransfer( pUsbDevice->UsbFuncs,
                                       Direction ? pUsbDevice->BulkIn.hPipe : pUsbDevice->BulkOut.hPipe,
                                       DefaultTransferComplete,
                                       Direction ? pUsbDevice->BulkIn.hEvent : pUsbDevice->BulkOut.hEvent,
                                       Direction ? (USB_IN_TRANSFER|USB_NO_WAIT|USB_SHORT_TRANSFER_OK) : (USB_OUT_TRANSFER|USB_NO_WAIT|USB_SHORT_TRANSFER_OK),
                                       pDataBlock, 0,
                                       dwRequestLength,
                                      &dwTransferLength,
                                       dwTimeout,
                                      &dwUsbErr );

            // accept any data received
            if ( (ERROR_SUCCESS == dwErr   || ERROR_TIMEOUT == dwErr) &&
                 (USB_NO_ERROR == dwUsbErr || USB_STALL_ERROR == dwUsbErr) ) 
            {
#if DEBUG
                if ( dwTransferLength != dwRequestLength ) {
                    DEBUGMSG( ZONE_WARN, (TEXT("CBIT_DataTransfer warning(a, RequestLength:%d TransferLength:%d Err:%d UsbErr:0x%x)\n"), dwRequestLength, dwTransferLength, dwErr, dwUsbErr ));
                }
#endif
                // adjust transfer length & buffer
                ASSERT(dwTransferLength <= dwRequestLength);
                pData->TransferLength += dwTransferLength;
                dwDataLength -= dwTransferLength;
                pDataBlock = (PVOID)((PBYTE)pDataBlock + dwTransferLength);
            }
            
            if ((ERROR_SUCCESS != dwErr) || (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));
                    dwDataLength = 0;
                }

                // protocol says its done
                if (USB_NO_ERROR != dwUsbErr) {
                    dwDataLength = 0;
                }
            
            } else {
                resets = 0;
            }

            dwTimeout -= (GetTickCount() - dwStartTime);
        }
    }


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 + -