📄 powerbutton.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
#include <windows.h>
#include <nkintr.h>
#include <windev.h>
#include <winbase.h>
#include "pwr.h"
#include <bsp.h>
#define SIZEOFARRAY(a) (sizeof(a) / sizeof(a[0]))
#define ENABLE TRUE
#define DISABLE FALSE
#define TICKTEST 0
#define SWRST_BTN 0
#define ww 1
// Make sure the driver builds OK in tinykern configuration
HMODULE g_hMod = NULL;
typedef void (*PFN_GwesPowerOffSystem)(void);
PFN_GwesPowerOffSystem g_pfnGwesPowerOffSystem = NULL;
//寄存器定义
volatile S3C2450_IOPORT_REG *v_pIOPregs;
volatile S3C2450_RTC_REG *v_pRTCregs;
volatile S3C2450_INTR_REG *v_pIntrRegs;
//睡眠和唤醒中断
UINT32 g_PwrButtonIrq = IRQ_EINT14; // #PWR_KEY
UINT32 g_PwrButtonSysIntr = SYSINTR_UNDEFINED;
//复位中断,这里没有用到
UINT32 g_ResetButtonIrq = IRQ_EINT15; //POWER_ON/OFF_RST
UINT32 g_ResetButtonSysIntr = SYSINTR_UNDEFINED;
HANDLE g_ResetThread;
HANDLE g_ResetEvent;
//中断线程
static DWORD PWR_IST(LPVOID Context);
/**********************************************************************************************
相关寄存器配置
***********************************************************************************************/
DWORD
HW_InitRegisters( PPWR_CONTEXT pPWR )
{
DWORD retry = 0;
RETAILMSG(ww, (TEXT("HW_InitRegisters start!!!1 \r\n")));
//虚拟地址分配
v_pIOPregs = (volatile S3C2450_IOPORT_REG *)VirtualAlloc(0, sizeof(S3C2450_IOPORT_REG), MEM_RESERVE, PAGE_NOACCESS);
VirtualCopy((PVOID)v_pIOPregs, (PVOID)(S3C2450_BASE_REG_PA_IOPORT >> 8), sizeof(S3C2450_IOPORT_REG), PAGE_PHYSICAL|PAGE_READWRITE|PAGE_NOCACHE );
v_pIntrRegs = (volatile S3C2450_INTR_REG *)VirtualAlloc(0, sizeof(S3C2450_INTR_REG), MEM_RESERVE, PAGE_NOACCESS);
VirtualCopy((PVOID)v_pIntrRegs, (PVOID)(S3C2450_BASE_REG_PA_INTR >> 8), sizeof(S3C2450_INTR_REG), PAGE_PHYSICAL|PAGE_READWRITE|PAGE_NOCACHE );
//GPG bit6 #PWR_KEY
v_pIOPregs->GPGDAT &= ~(0x1 << 6);
v_pIOPregs->GPGCON &= ~(0x3 <<12);
v_pIOPregs->GPGCON |= (0x2 << 12);
// EINT14 下降沿触发
v_pIOPregs->EXTINT1 = ((v_pIOPregs->EXTINT1) & ~(0xf<<24)) | (0x1 << 27)|(0x2 << 24);
RETAILMSG(ww, (TEXT("HW_InitRegisters over!!!! \r\n")));
return 0;
}
/*******************************************************************************************
// #PWR_KEY动态分配逻辑中断号,并进行与中断事件的关联
// 初始化的最后,创建PWR_IST 中断线程。
********************************************************************************************/
DWORD
HW_Init( PPWR_CONTEXT pPWR )
{
DWORD dwErr = ERROR_SUCCESS;
RETAILMSG(ww, (TEXT("HW_Init: start !!!! \r\n")));
if ( !pPWR )
return ERROR_INVALID_PARAMETER;
pPWR->State = INITIALIZE;
dwErr = HW_InitRegisters(pPWR);
if ( dwErr ) {
RETAILMSG(ww, (TEXT("HW_Init : HW_InitRegisters Error (0x%x) \r\n"), dwErr));
goto _error_exit;
}
RETAILMSG(ww, (TEXT("HW_Init : CreateEvent \r\n")));
pPWR->ISTEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
// #PWR_KEY ---申请逻辑中断号 -- 自动分配--中断关联
RETAILMSG(ww, (TEXT("HW_Init : IOCTL_HAL_REQUEST_SYSINTR \r\n")));
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &g_PwrButtonIrq, sizeof(UINT32), &g_PwrButtonSysIntr, sizeof(UINT32), NULL))
{
RETAILMSG(ww, (TEXT("ERROR: PwrButton: Failed to request sysintr value for power button interrupt.\r\n")));
return(0);
}
RETAILMSG(ww,(TEXT("INFO: PwrButton: Mapped Irq 0x%x to SysIntr 0x%x.\r\n"), g_PwrButtonIrq, g_PwrButtonSysIntr));
if (!(InterruptInitialize(g_PwrButtonSysIntr, pPWR->ISTEvent, 0, 0)))
{RETAILMSG(ww, (TEXT("ERROR: PwrButton: InterruptInitialize failed.\r\n"))); }
//启动线程
RETAILMSG(ww, (TEXT("HW_Init : CreateThread \r\n"), dwErr));
if ( (pPWR->IST = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) PWR_IST, pPWR, 0, NULL)) == NULL) {
dwErr = GetLastError( );
RETAILMSG(ww,(TEXT("PCF50606 ERROR: Unable to create IST: %u\r\n"), dwErr));
goto _error_exit;
}
//设置线程优先级
//RETAILMSG(ww, (TEXT("HW_Init : CeSetThreadPriority \r\n"), dwErr));
// TODO: registry override
if ( !CeSetThreadPriority(pPWR->IST, 250)) {
dwErr = GetLastError( );
RETAILMSG(ww, (TEXT("PCF50606 ERROR: CeSetThreadPriority ERROR:%d \r\n"), dwErr));
goto _error_exit;
}
pPWR->State = RUN;
RETAILMSG(ww, (TEXT("HW_Init : over !!!! \r\n"), dwErr));
_error_exit:
return dwErr;
}
/*******************************************************************************************
释放资源
********************************************************************************************/
DWORD
HW_Deinit( PPWR_CONTEXT pPWR )
{
RETAILMSG(ww,(TEXT("+PWR_Deinit \r\n")));
if ( !pPWR )
return ERROR_INVALID_PARAMETER;
pPWR->State = UNINITIALIZED;
if (pPWR->hADC && CloseHandle(pPWR->hADC))
pPWR->hADC = NULL;
if (pPWR->hTSCPRES && CloseHandle(pPWR->hTSCPRES))
pPWR->hTSCPRES = NULL;
if (pPWR->hI2C && pPWR->hI2C != INVALID_HANDLE_VALUE && CloseHandle(pPWR->hI2C))
pPWR->hI2C = INVALID_HANDLE_VALUE;
InterruptDisable(g_PwrButtonSysIntr);
if (pPWR->ISTEvent && CloseHandle(pPWR->ISTEvent))
pPWR->ISTEvent = NULL;
if (pPWR->IST && CloseHandle(pPWR->IST))
pPWR->IST = NULL;
// Free the coredll instance if we have allocated one
if(g_hMod) {
FreeLibrary(g_hMod);
g_hMod = NULL;
}
VirtualFree((PVOID) v_pIOPregs, 0, MEM_RELEASE);
VirtualFree((PVOID) v_pRTCregs, 0, MEM_RELEASE);
RETAILMSG(ww,(TEXT("-PWR_Deinit \r\n")));
return ERROR_SUCCESS;
}
/*******************************************************************************************
其他函数
********************************************************************************************/
DWORD
HW_Open( PPWR_CONTEXT pPWR )
{
RETAILMSG(ww, (TEXT("PCF: HW_Open \r\n")));
return ERROR_SUCCESS;
}
DWORD
HW_Close( PPWR_CONTEXT pPWR )
{
RETAILMSG(ww, (TEXT("PCF: HW_Close \r\n")));
return ERROR_SUCCESS;
}
/*******************************************************************************************
********************************************************************************************/
BOOL
HW_PowerUp( PPWR_CONTEXT pPWR )
{
RETAILMSG(ww, (TEXT("PCF: HW_PowerUp \r\n")));
pPWR->State = RESUME;
// pPWR->State = RUN;
// SetInterruptEvent(g_PwrButtonSysIntr);
return TRUE;
}
BOOL
HW_PowerDown( PPWR_CONTEXT pPWR )
{
RETAILMSG(ww, (TEXT("PCF: HW_PowerDown \r\n")));
pPWR->State = SUSPEND;
return TRUE;
}
/*******************************************************************************************
电源相关操作
********************************************************************************************/
BOOL
HW_PowerCapabilities( PPWR_CONTEXT pPWR, PPOWER_CAPABILITIES ppc )
{
return TRUE;
}
BOOL
HW_PowerSet( PPWR_CONTEXT pPWR,PCEDEVICE_POWER_STATE pDx )
{
CEDEVICE_POWER_STATE NewDx = *pDx;
if ( VALID_DX(NewDx) )
{
// We only support D0, so do nothing. Just return current state.
pPWR->Dx = *pDx = D0;
RETAILMSG(ww, (TEXT("PCF: IOCTL_POWER_SET: D%u => D%u \r\n"), NewDx, pPWR->Dx));
return TRUE;
}
return FALSE;
}
BOOL
HW_PowerGet(PPWR_CONTEXT pPWR, PCEDEVICE_POWER_STATE pDx )
{
// return our Current Dx value
*pDx = pPWR->Dx;
RETAILMSG(ww, (TEXT("PCF: IOCTL_POWER_GET: D%u \r\n"), pPWR->Dx));
return TRUE;
}
/*******************************************************************************************
关键函数
********************************************************************************************/
int OEM_SEU_PWRKEYSleep( )
{
HKEY hKey;
LONG lRes;
DWORD dwDelay, dwSize, dwType;
TCHAR WindowName[ ] = TEXT("DelayTime");
DWORD dwTime = 0, dwCount;
unsigned int status;
RETAILMSG(ww, (TEXT("OEM_SEU_PWRKEYSleep\r\n")));
//lRes = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("\\Drivers\\PowerManager\\PWRKEYDelay"), 0, 0, &hKey );
//if(ERROR_SUCCESS != lRes)
//{
//RETAILMSG(ww, (TEXT("RegOpenKeyEx( ) failed! error is %d \r\n"), GetLastError()));
//RegCloseKey(hKey);
//return -1;
//}
//dwSize = sizeof(DWORD);
//if(ERROR_SUCCESS == RegQueryValueEx( hKey, WindowName, NULL, &dwType, (PBYTE)&dwDelay, &dwSize))
//{
//dwCount = dwDelay / 50;
dwCount = 400 / 50;
while(1)
{
Sleep(50);
dwTime++;
status = v_pIOPregs->GPGDAT & (0x1<<6);
//按键2秒内弹起,保持唤醒
if( status == 1 )
{
RETAILMSG(ww, (TEXT("Inside OEM_SEU_PWRKEYSleep <2s return -2 !!!!!\r\n")));
//RegCloseKey(hKey);
return -2;
}
//按键长按2秒后才弹起,则进入睡眠状态
else if( dwTime >= dwCount )
{
RETAILMSG(ww, (TEXT("Inside OEM_SEU_PWRKEYSleep >2s return 0 !!!!!\r\n")));
//RegCloseKey(hKey);
return 0;
}
}
//}
// never hear
RETAILMSG(ww, (TEXT("OEM_SEU_PWRKEYSleep return -1 !!!!!\r\n")));
//return -1;
}
/*******************************************************************************************
重要线程
********************************************************************************************/
static DWORD
PWR_IST( PPWR_CONTEXT pPWR )
{
DWORD we;
WCHAR state[1024] = {0};
LPWSTR pState = &state[0];
DWORD dwBufChars = (sizeof(state) / sizeof(state[0]));
DWORD dwStateFlags = 0;
DWORD dwTimeout = 1000;
int Ret = 0;
DWORD dwPwrFlags;
TCHAR szPowerState[MAX_PATH];
RETAILMSG(ww,(TEXT("\r\nPWR_IST: enter PWR_IST:pPWR->State = 0x%x \r\n"), pPWR->State));
if (!pPWR)
return ERROR_INVALID_PARAMETER;
while (1) {
__try {
we = WaitForSingleObject(pPWR->ISTEvent, INFINITE);
RETAILMSG(ww,(TEXT("\r\nPWR_IST: pPWR->State = 0x%x \r\n"), pPWR->State));
if ((pPWR->State == RUN))
{
RETAILMSG(ww, (TEXT("pPWR->State == RUN!!! \r\n")));
Ret = OEM_SEU_PWRKEYSleep( );
switch(Ret)
{
case -1:
RETAILMSG(ww, (TEXT("Sleep \r\n")));
Sleep(100); //加入延时,防止睡眠按钮抖动
break;
case 0:
RETAILMSG(ww,(TEXT("\r\nPWR_IST: Call SetSystemPowerState Enter Suspend.... \r\n")));
SetSystemPowerState( NULL, POWER_STATE_SUSPEND, POWER_FORCE);
break;
default:
RETAILMSG(ww,(TEXT("\r\nPWR_IST: Press for long time to enter sleep mode!\r\n")));
// Back to "on" state if we are in "unattaneded" mode or "screenoff" mode.
GetSystemPowerState(szPowerState,SIZEOFARRAY(szPowerState),&dwPwrFlags);
if((wcscmp(szPowerState,L"unattended")==0) || (wcscmp(szPowerState,L"screenoff")==0))
{
// We are in"unattended" or "screenoff" mode. Go back to "on" state.
SetSystemPowerState(NULL,POWER_STATE_ON,POWER_FORCE);
// Block until the system is back to the "on" state.
do
{
Sleep(10);
GetSystemPowerState(szPowerState,SIZEOFARRAY(szPowerState),&dwPwrFlags);
} while(!(POWER_STATE(dwPwrFlags) & POWER_STATE_ON));
}
}
RETAILMSG(ww,(TEXT("pPWR->State == RUN over.. \r\n")));
//SetSystemPowerState( NULL, POWER_STATE_SUSPEND, POWER_FORCE );
}
else///APR if ( pPWR->State == 0x2 )
{
RETAILMSG(ww,(TEXT("pPWR->State is not RUN !!!!\r\n")));
SetSystemPowerState( NULL, POWER_STATE_ON, POWER_FORCE );
pPWR->State = RUN;
}
InterruptDone(g_PwrButtonSysIntr);
}
_except(EXCEPTION_EXECUTE_HANDLER)
{
RETAILMSG(ww,(TEXT("!!! PWR_IST EXCEPTION: 0x%X !!!\r\n"), GetExceptionCode( ) ));
}
}
}
/*******************************************************************************************
RealTime
********************************************************************************************/
BOOL
PWR_GetRealTime( PPWR_CONTEXT pPWR, LPSYSTEMTIME lpst)
{ return TRUE; }
BOOL
PWR_SetRealTime( PPWR_CONTEXT pPWR, LPSYSTEMTIME lpst )
{ return TRUE; }
/*******************************************************************************************
RealTime
********************************************************************************************/
BOOL
HW_IOControl(
PPWR_CONTEXT pPWR,
DWORD dwCode,
PBYTE pBufIn,
DWORD dwLenIn,
PBYTE pBufOut,
DWORD dwLenOut,
PDWORD pdwActualOut
)
{ return FALSE; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -