📄 plato_usbfn.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 + -