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

📄 powerbutton.c

📁 这是关于S3C2416平台上面关于睡眠唤醒的代码 写的很好很详尽
💻 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 + -