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

📄 plato_usbfn.cpp

📁 Windows CE 6.0 BSP for VOIP sample phone. Intel PXA270 platform.
💻 CPP
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
/*++

THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name: 

        plato_usbfn.cpp

Abstract:

        Plato USB Function Driver.

--*/

#include <windows.h>
#include <ceddk.h>
#include <ddkreg.h>
#include <nkintr.h> // needed for SYSINTR_NOP

#include <bulverde.h>
#include <bulverde_intr.h>
#include <bulverde_gpio.h>
#include <bul_usbfn.h>


class PlatoUsbDevice: public BulUsbDevice 
{
public:
    PlatoUsbDevice(LPCTSTR lpActivePath)
    :  BulUsbDevice(lpActivePath)
    {
        m_pGPIORegs = NULL;    
        m_pPwrRst_reg = NULL;
        m_dwCDIrq = 0;
        m_dwSysintrCD = SYSINTR_UNDEFINED;
        m_dwCDIstThreadPriority = 150;
        m_hStopCDIst = FALSE;
        m_hCDInterruptEvent = NULL;
        m_hCDInterruptThread = NULL;
    }
    virtual ~PlatoUsbDevice() 
    {
        CleanupCableDetectIST();
        
        if (m_pGPIORegs)
            MmUnmapIoSpace(m_pGPIORegs,0);

        if (m_pPwrRst_reg)
            MmUnmapIoSpace(m_pPwrRst_reg,0);
    }

    virtual DWORD Init(PVOID pvMddContext,PUFN_MDD_INTERFACE_INFO pMddInterfaceInfo, PUFN_PDD_INTERFACE_INFO pPddInterfaceInfo) 
    {
        DWORD dwReturn = ERROR_INVALID_DATA;
        if (m_pGPIORegs==NULL) 
        {
            PHYSICAL_ADDRESS ioPhysicalBase = { BULVERDE_BASE_REG_PA_GPIO, 0 };
            m_pGPIORegs =(PBULVERDE_GPIO_REG) MmMapIoSpace(ioPhysicalBase, sizeof(BULVERDE_GPIO_REG),FALSE) ;
        }

        if (m_pPwrRst_reg==NULL) 
        {
            PHYSICAL_ADDRESS ioPhysicalBase = { BULVERDE_BASE_REG_PA_PWR, 0 };
            m_pPwrRst_reg =(PBULVERDE_PWRRST_REG) MmMapIoSpace(ioPhysicalBase, sizeof(BULVERDE_PWRRST_REG),FALSE) ;
        }
        

        if (m_pGPIORegs) 
        {
            // Setup GPIOs for the USB device controller on Plato

            // pull GPIO pin 11 low to detach the device from the bus (to start with)
            m_pGPIORegs->GPCR0 |= XLLP_BIT_11;

            // set GPIO pin 11 direction to output (soft connect/dis-connect)
            m_pGPIORegs->GPDR0 |= XLLP_BIT_11;            

            // set GPIO pin 22 direction to input (cable attach detect)
            m_pGPIORegs->GPDR0 &= ~XLLP_BIT_22;

            // set GPIO pin 22 edge detect registers (cable attach detect)
            m_pGPIORegs->GRER0 |= XLLP_BIT_22;   // rising edge
            m_pGPIORegs->GFER0 |= XLLP_BIT_22;   // falling edge

            // set GPIO alternate function registers for the two GPIOs
            m_pGPIORegs->GAFR0_L &= 0x3FFFFFFF;
            m_pGPIORegs->GAFR0_L &= 0xFFFFCFFF;
            
            dwReturn = BulUsbDevice::Init(pvMddContext, pMddInterfaceInfo, pPddInterfaceInfo);

            m_dwCDIrq = IRQ_GPIOXX_2_GPIO22;
            SetupCableDetectDetectIST( this );
        }
        return dwReturn;
       
    }

    virtual DWORD Start() 
    {
        DWORD dwReturn = BulUsbDevice::Start();
        if (dwReturn == ERROR_SUCCESS) 
        {
            // Enable UDC Soft Connect
            // Pull GPIO pin 11 high to attach the device to the bus
            m_pGPIORegs->GPSR0 |= XLLP_BIT_11;
        }
        return dwReturn;
    }

    virtual DWORD Stop() 
    {
        DWORD dwReturn = BulUsbDevice::Stop();
        if (dwReturn == ERROR_SUCCESS) 
        {
            // Enable UDC Soft Disconnect
            // pull GPIO pin 11 low to detach the device from the bus
            m_pGPIORegs->GPCR0 |= XLLP_BIT_11;
        }
        return dwReturn;
    }

    virtual BOOL IsCableAttached() 
    { 
        return ((m_pGPIORegs->GPLR0 & XLLP_BIT_22)!=0); 
    };
    
protected:
    virtual void PowerMgr(BOOL bOff) 
    {
        if (bOff) 
        {
            // Pull GPIO pin 11 low to detach the device from the bus
            m_pGPIORegs->GPCR0 |= XLLP_BIT_11;
            m_fIsCableAttached = FALSE;
        }
        else
        {
            // Clear the OTGPH (OTG Peripheral Hold) bit in PSSR.
            // This will enable the USB lines again.
            m_pPwrRst_reg->pssr |= 0x40;

            // We don't need to do software connect here because, IST will call Start to get it reconnected.
        }
        
        BulUsbDevice::PowerMgr(bOff);
    }

    static DWORD CableDetectIstThread(void *pContext)
    {
        DWORD waitStatus;
        DWORD dwTimeout = INFINITE;
        PlatoUsbDevice* m_pUsbDevice = (PlatoUsbDevice *)pContext;

        if (pContext == NULL)
        {
            DEBUGMSG(ZONE_ERROR,(TEXT("PlatoUsbDevice: ERROR!!! CableDetectIstThread got invalid context. \r\n")));
            return 0;
        }

        CeSetThreadPriority(GetCurrentThread(), m_pUsbDevice->m_dwCDIstThreadPriority);

        while(TRUE)
        {
            waitStatus = WaitForSingleObject( m_pUsbDevice->m_hCDInterruptEvent, dwTimeout );

            if (WAIT_OBJECT_0 != waitStatus ||
                m_pUsbDevice->m_hStopCDIst) 
            {
                return 0;
            }

            RETAILMSG(1,(TEXT("PlatoUsbFn: CableDetect Changed. Sending event to parent IST")));

            // Cable Detect status changed. Notify the parent IST
            SetInterruptEvent(m_pUsbDevice->m_dwSysIntr);

            InterruptDone( m_pUsbDevice->m_dwSysintrCD );
        } // while
    }

    BOOL  SetupCableDetectDetectIST( void *pHardwareContext )
    {
        DWORD threadID;

        // convert the hardware cable detect interrupt IRQ into a logical SYSINTR value
        if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &m_dwCDIrq, sizeof(DWORD), &(m_dwSysintrCD), sizeof(DWORD), NULL))
        {
            // invalid SDIO SYSINTR value!
            DEBUGMSG(ZONE_ERROR, (TEXT("Error obtaining Cable Detect IRQ SYSINTR value!\n")));
            m_dwSysintrCD = SYSINTR_UNDEFINED;
            return FALSE;
        }

        // allocate the interrupt event for cable detect
        m_hCDInterruptEvent = CreateEvent(NULL, FALSE, FALSE,NULL);
        if (NULL == m_hCDInterruptEvent) 
        {
            DEBUGMSG(ZONE_ERROR, (TEXT("Failed to Initialize Cable Detect interrupt event!\n")));
            return FALSE;
        }

        // initialize the cable detect interrupt event
        if (!InterruptInitialize (m_dwSysintrCD,
                                m_hCDInterruptEvent,
                                NULL,
                                0)) 
        {
            DEBUGMSG(ZONE_ERROR, (TEXT("Failed to Initialize Cable Detect interrupt!\n")));
            return FALSE;
        }

        InterruptDone(m_dwSysintrCD);

        // create the interrupt thread to handle card insertion events
        m_hCDInterruptThread =  CreateThread(NULL,
                                             0,
                                             (LPTHREAD_START_ROUTINE)CableDetectIstThread,
                                             pHardwareContext,
                                             0,
                                             &threadID);
        
        if (NULL == m_hCDInterruptThread) 
        {
            DEBUGMSG(ZONE_ERROR, (TEXT("Failed to Initialize Cable Detect interrupt thread!\n")));
            return FALSE;
        }

        return TRUE;
    }

    void CleanupCableDetectIST()
    {
        // wake up the IST
        if( m_hCDInterruptEvent )
        {
            m_hStopCDIst = TRUE;
            SetEvent(m_hCDInterruptEvent);
        }

        // clean up card insertion IST 
        if (NULL != m_hCDInterruptThread) 
        {
            // wait for the thread to exit
            WaitForSingleObject(m_hCDInterruptThread, INFINITE); 
            CloseHandle(m_hCDInterruptThread);
            m_hCDInterruptThread = NULL;
        }

        // free card insertion interrupt event
        if (NULL != m_hCDInterruptEvent) {
            CloseHandle(m_hCDInterruptEvent);
            m_hCDInterruptEvent = NULL;
        }

        // free card insertion interrupt
        if( m_dwSysintrCD != SYSINTR_UNDEFINED )
        {
            InterruptDisable( m_dwSysintrCD );
            KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &m_dwSysintrCD, sizeof(DWORD), NULL, 0, NULL);
            m_dwSysintrCD = SYSINTR_UNDEFINED;
        }
    }

private:
    volatile PBULVERDE_GPIO_REG m_pGPIORegs;
    volatile PBULVERDE_PWRRST_REG m_pPwrRst_reg;

    DWORD m_dwCDIrq;
    DWORD m_dwSysintrCD;
    DWORD m_dwCDIstThreadPriority;
    BOOL m_hStopCDIst;
    HANDLE m_hCDInterruptEvent;
    HANDLE m_hCDInterruptThread;

};


BulUsbDevice * CreateBulUsbDevice(LPCTSTR lpActivePath)
{
    return new PlatoUsbDevice(lpActivePath);
}

⌨️ 快捷键说明

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