bul_usbfn.cpp

来自「pxa27x library for windows ce 5.0」· C++ 代码 · 共 1,704 行 · 第 1/4 页

CPP
1,704
字号
                        bContinue = TRUE;
                        continue;
                    }
                }
                else { // Error
                    udccsr.ep0bit.FST = 1;
                }
            }
            else { // Transfer Not queue yet. 
                //m_pUsbDevice->EnableEndpointInterrupt(m_dwEndpointIndex,FALSE);
                // Do not clean OPC
                udccsr.ep0bit.OPC = 0;
            }

        }
        if (udccsr.ep0bit.IPR==0 ) {
        // Because the Ep0 is half duplex. We assume the direction is correct.
            if (m_pCurTransfer && (m_pCurTransfer->dwFlags & USB_IN_TRANSFER)!=0 &&
                    m_pCurTransfer->cbTransferred <= m_pCurTransfer->cbBuffer) {
                DWORD dwTotalData = m_pCurTransfer->cbBuffer - m_pCurTransfer->cbTransferred ;
                dwTotalData = min (dwTotalData,m_epDesc.wMaxPacketSize) ;
                // Spec 12.5.5
                DWORD dwReturn = XmitData(((PBYTE)m_pCurTransfer->pvBuffer)+ m_pCurTransfer->cbTransferred, dwTotalData );
                ASSERT(dwReturn == dwTotalData);
                m_pCurTransfer->cbTransferred += dwReturn;
                if (dwTotalData< m_epDesc.wMaxPacketSize) {
                    udccsr.ep0bit.IPR = 1;
                    m_fZeroPacket = FALSE;
                }
                else 
                    m_fZeroPacket = TRUE;
            }
        }
        else 
            udccsr.ep0bit.IPR = 0 ; // Do not set when there is packet.
            
        if (udccsr.ep0bit.SST) { // Stall happens.
            DEBUGMSG(ZONE_WARNING, (_T("Stall Sent on Zero endpoint =0x%x"),m_dwEndpointIndex));
        }
        // Clean the status.
        WriteControlStatusRegister( udccsr.ulValue);
        if (m_pCurTransfer &&m_pCurTransfer->cbTransferred >= m_pCurTransfer->cbBuffer && !m_fZeroPacket) {// Complete anyway
            CompleteTransfer(UFN_NO_ERROR);
        }
        
    }
    m_fInIST = FALSE;
    Unlock();
    FUNCTION_LEAVE_MSG();
    return ERROR_SUCCESS;
}
DWORD   BulEndpointIn::IST(DWORD dwIRBit)
{
    Lock();
    BOOL bContinue = TRUE;
    SETFNAME();
    FUNCTION_ENTER_MSG();
    if ((dwIRBit & EPINT_FIFO_ERROR)!=0) { // FIFO Error. End
        DWORD dwUdccsr;
        dwUdccsr = ReadControlStatusRegister();
        DEBUGMSG(ZONE_WARNING, (_T("FIFO Error on Endpoint IN(%d) UDCCSR=0x%x"),m_dwEndpointIndex,dwUdccsr));
    }

    while (bContinue) 
    { // Loop until all the event clear.
        bContinue = FALSE;
        UDCCSR udccsr;
        udccsr.ulValue = ReadControlStatusRegister();
        DEBUGMSG(ZONE_TRANSFER, (_T(" IN::IST(%d) UDCCSR=0x%x"),m_dwEndpointIndex,udccsr.ulValue));
        if (m_fStalled && (udccsr.epbit.PC!=0 || udccsr.epbit.TRN!=0) ) {
            // Stall has been clear silently. So we generate Faking Clear Feature for Endpoint Zero
            m_fStalled = FALSE;
            udccsr.epbit.PC = udccsr.epbit.TRN = udccsr.epbit.FEF = 0;
            WriteControlStatusRegister(udccsr.ulValue);
            bContinue = TRUE;
            SendFakeFeature(USB_REQUEST_CLEAR_FEATURE,USB_FEATURE_ENDPOINT_STALL);
            continue;
        }
        if ( udccsr.epbit.PC!=0 ) { // Packet Complete.
            if (udccsr.epbit.DPE!=0 ) { // Data Packet Error
                WriteControlStatusRegister(udccsr.ulValue);
                CompleteTransfer( UFN_NOT_COMPLETE_ERROR );
                continue;
            }
            if ( m_pCurTransfer && !m_fZeroPacket &&  m_pCurTransfer->cbTransferred >= m_pCurTransfer->cbBuffer) {
                WriteControlStatusRegister(udccsr.ulValue);        
                CompleteTransfer(UFN_NO_ERROR);
                continue;
            }
            bContinue = TRUE;
        }
        udccsr.epbit.SP = 0;
        if ( udccsr.epbit.FS!=0 && m_pCurTransfer!=NULL  && 
                (m_pCurTransfer->cbTransferred < m_pCurTransfer->cbBuffer || m_fZeroPacket) )  { // Include Eaqual for 0 packet.
            ASSERT((m_pCurTransfer->dwFlags & USB_IN_TRANSFER)!=NULL);
            DWORD dwXmitLength = (m_fZeroPacket?0:m_pCurTransfer->cbBuffer-m_pCurTransfer->cbTransferred);
            dwXmitLength = XmitData((PBYTE)m_pCurTransfer->pvBuffer + m_pCurTransfer->cbTransferred, dwXmitLength );
            m_pCurTransfer->cbTransferred += dwXmitLength;
            m_fZeroPacket = FALSE;
            if (dwXmitLength < m_epDesc.wMaxPacketSize) {
                udccsr.epbit.SP = 1;
                m_fZeroPacket = FALSE;
            }
            else
                m_fZeroPacket = FALSE;
            bContinue = TRUE;
        }
        if (udccsr.epbit.SST) {
            DEBUGMSG(ZONE_WARNING, (_T("Stall send on In Endpoint = 0x%x"),m_dwEndpointIndex));
            m_fStalled = TRUE;
            bContinue = TRUE;
        }
        WriteControlStatusRegister(udccsr.ulValue);        
    }
    Unlock();
    FUNCTION_LEAVE_MSG();
    return ERROR_SUCCESS;
}
DWORD   BulEndpointOut::IST(DWORD dwIRBit)
{
    Lock();
    BOOL bContinue = TRUE;
    SETFNAME();
    FUNCTION_ENTER_MSG();
    if ((dwIRBit & EPINT_FIFO_ERROR)!=0) { // FIFO Error. End
        DWORD dwUdccsr;
        dwUdccsr = ReadControlStatusRegister();
        DEBUGMSG(ZONE_WARNING, (_T("FIFO Error on Endpoint Out(%d) UDCCSR=0x%x"),m_dwEndpointIndex,dwUdccsr));
    }

    while (bContinue) {
        bContinue = FALSE;
        UDCCSR udccsr;
        udccsr.ulValue = ReadControlStatusRegister();
        DEBUGMSG(ZONE_TRANSFER, (_T(" Out::IST(%d) UDCCSR=0x%x"),m_dwEndpointIndex,udccsr.ulValue));
        if (m_fStalled && (udccsr.epbit.PC!=0 || udccsr.epbit.TRN!=0) ) {
            // Stall has been clear silently. So we generate Faking Clear Feature for Endpoint Zero
            m_fStalled = FALSE;
            udccsr.epbit.PC = udccsr.epbit.TRN = udccsr.epbit.FEF = 0;
            WriteControlStatusRegister(udccsr.ulValue);
            bContinue = TRUE;
            SendFakeFeature(USB_REQUEST_CLEAR_FEATURE,USB_FEATURE_ENDPOINT_STALL);
            continue;
        }
        // Unload in data if there is any
        if  ( udccsr.epbit.FS!=0 && m_pCurTransfer!=NULL  && 
                m_pCurTransfer->cbTransferred < m_pCurTransfer->cbBuffer)  { // Include Eaqual for 0 packet.
            DWORD dwReceiveLength = min (ReadByteCountRegister(),m_pCurTransfer->cbBuffer - m_pCurTransfer->cbTransferred);
            dwReceiveLength = ReceiveData((PBYTE)m_pCurTransfer->pvBuffer + m_pCurTransfer->cbTransferred,dwReceiveLength);
            m_pCurTransfer->cbTransferred += dwReceiveLength;
            if (m_pCurTransfer->cbTransferred >= m_pCurTransfer->cbBuffer) {
                WriteControlStatusRegister(udccsr.ulValue);
                CompleteTransfer(UFN_NO_ERROR);
                continue;
            }
            else
                bContinue = TRUE;
                
        }
        if ( udccsr.epbit.PC!=0 ) { // Packet Complete.
            if (udccsr.epbit.DPE!=0 ) { // Data Packet Error
                WriteControlStatusRegister(udccsr.ulValue);
                CompleteTransfer( UFN_NOT_COMPLETE_ERROR );
                continue;
            }
            if ( m_pCurTransfer) {
                if (m_pCurTransfer->cbTransferred >= m_pCurTransfer->cbBuffer) {
                    WriteControlStatusRegister(udccsr.ulValue);
                    CompleteTransfer(UFN_NO_ERROR);
                    continue;
                }
                else if (udccsr.epbit.SP ){
                    WriteControlStatusRegister(udccsr.ulValue);
                    CompleteTransfer(UFN_NO_ERROR);
                    continue;
                }
                bContinue = TRUE;
            }
            else { // Not ready yet.
                //m_pUsbDevice->EnableEndpointInterrupt(m_dwEndpointIndex,FALSE);
                // Do not clean anything
                udccsr.epbit.PC = 0;
                bContinue = FALSE;
            }
        }
        if (udccsr.epbit.SST) {
            DEBUGMSG(ZONE_WARNING, (_T("Stall Sent on Out endpoint =0x%x"),m_dwEndpointIndex));
            m_fStalled = TRUE;
            bContinue = TRUE;
        }
        WriteControlStatusRegister(udccsr.ulValue);
    }
    Unlock();
    FUNCTION_LEAVE_MSG();
    return ERROR_SUCCESS;
}
BulUsbDevice::BulUsbDevice(LPCTSTR lpActivePath )
:   CRegistryEdit(lpActivePath)
,   CMiniThread (0, TRUE)   
{
    m_pUsbDevReg = NULL;
    for (DWORD dwIndex =0 ; dwIndex <MAX_ENDPOINT_NUMBER; dwIndex ++) {
        m_EndpointArray[dwIndex] = NULL;
    }
    m_hISTEvent = NULL;
    m_pDCCLKReg = NULL;
    m_fDoubleBuffer = TRUE;
    m_pvMddContext = NULL;
    m_dwCurConfigure = MAXDWORD;
    m_dwCurInterface = MAXDWORD;
    m_pfnNotify = NULL;
    m_CurPowerState = PwrDeviceUnspecified ;
    m_hParent = CreateBusAccessHandle(lpActivePath);    
}

BulUsbDevice::~BulUsbDevice()
{
    if (m_hParent)
        CloseBusAccessHandle(m_hParent);
    
    if (m_pUsbDevReg!=NULL) {
        WriteIntrCtr0Register(0);
        WriteIntrCtr1Register(0);
        WriteControlRegister(0) ;
        MmUnmapIoSpace((PVOID)m_pUsbDevReg,0UL);
    }
    if (m_hISTEvent) {
        m_bTerminated=TRUE;
        ThreadStart();
        SetEvent(m_hISTEvent);
        ThreadTerminated(1000);
        InterruptDisable( m_dwSysIntr );         
        CloseHandle(m_hISTEvent);
    };
    for (DWORD dwIndex =0 ; dwIndex <MAX_ENDPOINT_NUMBER; dwIndex ++) {
        if (m_EndpointArray[dwIndex] != NULL)
            delete m_EndpointArray[dwIndex];
    }

    if (m_pDCCLKReg) {
        m_pDCCLKReg->cken &= ~XLLP_CLKEN_USBCLIENT ;
        MmUnmapIoSpace(m_pDCCLKReg,0);
    }
}
DWORD BulUsbDevice::Init(
    PVOID                       pvMddContext,
    PUFN_MDD_INTERFACE_INFO     pMddInterfaceInfo,
    PUFN_PDD_INTERFACE_INFO     pPddInterfaceInfo
    )
{
    m_pvMddContext = pvMddContext;
    m_pfnNotify = pMddInterfaceInfo->pfnNotify;
    pPddInterfaceInfo->pvPddContext = this;
    
    if ( !IsKeyOpened())
        return ERROR_INVALID_DATA; 
    
    DDKISRINFO dii;
    DDKWINDOWINFO dwi;
    DWORD dwRet = GetWindowInfo(&dwi);
    if(dwRet != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_INIT, (_T("BulUsbDevice:: DDKReg_GetWindowInfo() failed %d\r\n"), dwRet));
        return dwRet;
    } else if(dwi.dwNumMemWindows != 1) {
        return ERROR_INVALID_DATA;
    }  else if (dwi.memWindows[0].dwLen < sizeof(BULVERDE_USBD_REG)) {
        DEBUGMSG(ZONE_INIT, (_T("memLen of 0x%x is less than required 0x%x\r\n"),
            dwi.memWindows[0].dwLen, sizeof(BULVERDE_USBD_REG)));
        return ERROR_INVALID_DATA;
    }
    m_fIsCableAttached = FALSE;
    if (m_pDCCLKReg == NULL ) {
        PHYSICAL_ADDRESS ioPhysicalBase = {BULVERDE_BASE_REG_PA_CLKMGR, 0 };
        m_pDCCLKReg = (PBULVERDE_CLKMGR_REG)MmMapIoSpace(ioPhysicalBase, sizeof(BULVERDE_CLKMGR_REG),FALSE);
        if (m_pDCCLKReg != NULL)
            m_pDCCLKReg->cken |= XLLP_CLKEN_USBCLIENT ;
        else
            return ERROR_INVALID_DATA;            
    }

    // Map Windows.
    // Translate to System Address.
    if (m_pUsbDevReg==NULL ) {
        PHYSICAL_ADDRESS    ioPhysicalBase = { dwi.memWindows[0].dwBase, 0};
        m_pUsbDevReg = (PULONG) MmMapIoSpace(ioPhysicalBase, dwi.memWindows[0].dwLen,FALSE);
        if (m_pUsbDevReg==NULL )
            return ERROR_INVALID_DATA;
    }
    // get ISR configuration information
    dwRet = GetIsrInfo( &dii);
    if(dwRet != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_INIT, (_T("BulUsbDevice DDKReg_GetIsrInfo() failed %d\r\n"), dwRet));
        return dwRet;
    } else if(dii.dwSysintr == SYSINTR_NOP){
        DEBUGMSG(ZONE_INIT, (_T("BulUsbDevice  no SYSINTR value specified\r\n")));
        return ERROR_INVALID_DATA;
    };
    m_dwSysIntr = dii.dwSysintr;
    m_hISTEvent= CreateEvent(0,FALSE,FALSE,NULL);
    if (m_hISTEvent!=NULL)
        InterruptInitialize(m_dwSysIntr,m_hISTEvent,0,0);
    else
       return ERROR_INVALID_DATA;
        
    // Optional Registry.
    DWORD dwDataSize = sizeof(DWORD);
    DWORD dwDoubleBuffer = 1;
    if (!GetRegValue(BUL_USBFUNCTION_DOUBLEBUFFER_VALNAME, (LPBYTE) &dwDoubleBuffer,dwDataSize)){
        dwDoubleBuffer = 1;
    };
    m_fDoubleBuffer = (dwDoubleBuffer==1);
    // Read the IST priority
    dwDataSize = sizeof(m_dwPriority);
    if (!GetRegValue(BUL_USBFUNCTION_PRIORITY_VALNAME,(LPBYTE) &m_dwPriority, dwDataSize)) {
        m_dwPriority = BUL_USBFUNCTION_DEFAULT_PRIORITY;
    }
    CeSetPriority(m_dwPriority);
    if (HardwareInit()) {
        ThreadStart();
        return ERROR_SUCCESS;
    }
    else
        return ERROR_INVALID_DATA;
}
BOOL BulUsbDevice::HardwareInit()
{
    BOOL bReturn = TRUE;
    SETFNAME();
    FUNCTION_ENTER_MSG();
    Lock();
    // Disable Hardware
    UDCCR udccr;
    udccr.ulValue = ReadControlRegister();
    udccr.bit.UDE= udccr.bit.EMCE = 0;
    WriteControlRegister(udccr.ulValue);
    WriteIntrCtr0Register(0);
    WriteIntrCtr1Register(0); 
    // Ack all outstanding interrupt.
    WriteIntrStatus0Register(0xffffffff);
    WriteIntrStatus1Register(0xffffffff);
    Unlock();
    FUNCTION_LEAVE_MSG();
    return bReturn;
}
BOOL   BulUsbDevice::ReInit() // For Cable Detach & Attach , We have to re-init the Device Controller.
{
    Lock();
    HardwareInit();
    for (DWORD dwIndex=0; dwIndex<MAX_ENDPOINT_NUMBER; dwIndex++)
        if (m_EndpointArray[dwIndex]!=NULL) 
            m_EndpointArray[dwIndex]->ReInit();
        
    //PVOID pvMddContext = m_pvMddContext;
    //m_pvMddContext = NULL;
    Start();
    
    for (dwIndex=0; dwIndex<MAX_ENDPOINT_NUMBER; dwIndex++)
        if (m_EndpointArray[dwIndex]!=NULL) {
            EnableEndpointInterrupt(dwIndex, TRUE);
        }
    
    Unlock();
    return FALSE;
}
BOOL BulUsbDevice::DeleteAllEndpoint()
{
    Lock();
    for (DWORD dwIndex=0; dwIndex<MAX_ENDPOINT_NUMBER; dwIndex++)
        if (m_EndpointArray[dwIndex]!=NULL) {
            delete m_EndpointArray[dwIndex];
            m_EndpointArray[dwIndex] = NULL;
        }
    
    Unlock();
    return TRUE;
}

//
#define UDCIR0_MAX 0x10
BOOL   BulUsbDevice::EnableEndpointInterrupt(DWORD dwEndpointIndex,BOOL bEnable)
{
    SETFNAME();
    DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Enter. dwEndpoint:0x%x,Enable:0x%x --\r\n"), pszFname,dwEndpointIndex,bEnable));
    
    if (dwEndpointIndex < MAX_ENDPOINT_NUMBER ) {
        Lock();
        if (dwEndpointIndex <UDCIR0_MAX) {
            DWORD dwIntrCtrBit = ((EPINT_PACKET_COMPLETE | EPINT_FIFO_ERROR) <<(dwEndpointIndex*2));
            DWORD dwIntrCtl = ReadIntrCtr0Register() ;
            if (bEnable)
                dwIntrCtl |= dwIntrCtrBit;
            else 
                dwIntrCtl &= ~dwIntrCtrBit;
            WriteIntrCtr0Register(dwIntrCtl);
        }
        else {
            dwEndpointIndex -= UDCIR0_MAX;
            DWORD dwIntrCtrBit = ((EPINT_PACKET_COMPLETE | EPINT_FIFO_ERROR) <<(dwEndpointIndex*2));
            DWORD dwIntrCtl = ReadIntrCtr1Register() ;
            if (bEnable)
                dwIntrCtl |= dwIntrCtl;
            else 
                dwIntrCtl &= ~dwIntrCtl;
            WriteIntrCtr1Register(dwIntrCtl);
        }
        Unlock();
        return TRUE;
    }
    return FALSE;
}
DWORD  BulUsbDevice::GetEndpointIntrStatus(DWORD dwEndpointIndex)
{
    DWORD dwReturnStatus = 0;
    if (dwEndpointIndex < MAX_ENDPOINT_NUMBER ) {
        if (dwEndpointIndex <UDCIR0_MAX) {
            dwReturnStatus = (ReadIntrStatus0Register()>>(dwEndpointIndex*2)) & (EPINT_PACKET_COMPLETE | EPINT_FIFO_ERROR);
        }
        else {
            dwEndpointIndex -= MAX_ENDPOINT_NUMBER;
            dwReturnStatus = (ReadIntrStatus1Register()>>(dwEndpointIndex*2)) & (EPINT_PACKET_COMPLETE | EPINT_FIFO_ERROR);
        }
    }
    return dwReturnStatus;
}


⌨️ 快捷键说明

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