📄 pwrbtn2410.c
字号:
//
// 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.
//
//
// This driver uses the SW1 button on EINT0 for suspend/resume.
// SW2 (EINT2) is for reset.
//
#include <windows.h>
#include <types.h>
#include <nkintr.h>
#include <pm.h>
#include <s3c2410x.h>
// Should match type of SetSystemPowerState() in pm.h
typedef DWORD (*PFN_SetSystemPowerState)(LPCWSTR, DWORD, DWORD);
static PFN_SetSystemPowerState pfnSetSystemPowerState;
static HANDLE PwrButtonIntrEvent;
static HANDLE PowerButtonIntrThreadHandle;
static HANDLE ResetButtonIntrEvent;
static HANDLE ResetButtonIntrThreadHandle;
static DWORD PwrButtonIrq = IRQ_EINT0; // Determined by SMDK2410 board layout.
static DWORD PwrButtonSysIntr = SYSINTR_UNDEFINED;
static DWORD ResetButtonIrq = IRQ_EINT2; // Determined by SMDK2410 board layout.
static DWORD ResetButtonSysIntr = SYSINTR_UNDEFINED;
static volatile S3C2410X_IOPORT_REG *v_pIOPregs;
static volatile S3C2410X_INTR_REG *s2410INT;
static VOID
EnablePowerButtonInterrupt(VOID)
{
v_pIOPregs->GPFCON &= ~(0x3 << 0); // Set EINT0(GPF0) as EINT0
v_pIOPregs->GPFCON |= (0x2 << 0);
v_pIOPregs->EXTINT0 &= ~(0x7 << 0); // Configure EINT0 as Falling Edge Mode
v_pIOPregs->EXTINT0 |= (0x2 << 0);
}
static VOID
EnableResetButtonInterrupt(VOID)
{
v_pIOPregs->GPFCON &= ~(0x3 << 4); // Set EINT2(GPF2) as EINT2
v_pIOPregs->GPFCON |= (0x2 << 4);
v_pIOPregs->EXTINT0 &= ~(0x7 << 8); // Configure EINT2 as Falling Edge Mode
v_pIOPregs->EXTINT0 |= (0x2 << 8);
}
static BOOL
PowerButtonIsPushed(VOID)
{
//
// Switches are pulled up when open, and driven low when closed.
// Return true if switch 1 (EINT0) is closed.
//
return ((v_pIOPregs->GPFDAT & (1 << 0)) ? FALSE : TRUE);
}
static BOOL
ResetButtonIsPushed(VOID)
{
//
// Switches are pulled up when open, and driven low when closed.
// Return true if switch 1 (EINT2) is closed.
//
return ((v_pIOPregs->GPFDAT & (1 << 2)) ? FALSE : TRUE);
}
static BOOL
InitializeAddresses(VOID)
{
BOOL RetValue = FALSE;
// IO Register Allocation
v_pIOPregs = (volatile S3C2410X_IOPORT_REG *)VirtualAlloc(0, sizeof *v_pIOPregs, MEM_RESERVE, PAGE_NOACCESS);
if (v_pIOPregs == NULL)
{
ERRORMSG(1,(TEXT("PBT: VirtualAlloc failed!\r\n")));
} else {
if (!VirtualCopy((PVOID)v_pIOPregs, (PVOID)(S3C2410X_BASE_REG_PA_IOPORT >> 8), sizeof *v_pIOPregs, PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
{
ERRORMSG(1,(TEXT("PBT: VirtualCopy failed!\r\n")));
VirtualFree((PVOID)v_pIOPregs, 0, MEM_RELEASE);
v_pIOPregs = NULL;
}
}
s2410INT = (volatile S3C2410X_INTR_REG *)VirtualAlloc(0, sizeof *s2410INT, MEM_RESERVE, PAGE_NOACCESS);
if (s2410INT == NULL)
{
ERRORMSG(1,(TEXT("PBT: VirtualAlloc failed!\r\n")));
} else {
if (!VirtualCopy((PVOID)s2410INT, (PVOID)(S3C2410X_BASE_REG_PA_INTR >> 8), sizeof *s2410INT, PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
{
ERRORMSG(1,(TEXT("PBT: VirtualCopy failed!\r\n")));
VirtualFree((PVOID)s2410INT, 0, MEM_RELEASE);
s2410INT = NULL;
}
}
if(v_pIOPregs && s2410INT)
{
RetValue = TRUE;
}
return (RetValue);
}
static DWORD
PowerButtonIntrThread(PVOID pArg)
{
EnablePowerButtonInterrupt();
PwrButtonIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
//
// Request a SYSINTR value from the OAL.
//
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &PwrButtonIrq, sizeof PwrButtonIrq, &PwrButtonSysIntr, sizeof PwrButtonSysIntr, NULL))
{
RETAILMSG(1, (TEXT("PBT: Error! Failed to request sysintr value for power button interrupt.\r\n")));
return(0);
}
if (!(InterruptInitialize(PwrButtonSysIntr, PwrButtonIntrEvent, 0, 0)))
{
RETAILMSG(1, (TEXT("ERROR: PwrButton: Interrupt initialize failed.\r\n")));
}
// Handle power button presses.
for (;;)
{
WaitForSingleObject(PwrButtonIntrEvent, INFINITE);
if (PowerButtonIsPushed()) // Guard against noise triggering an interrupt.
{
Sleep(200); // Check again in 200 Ms. to fend off a continuous press.
if (!PowerButtonIsPushed()) // Must be held+released in less than .2 seconds.
{
//
// Soft reset and standard suspend-resume both start with suspend for now.
// Call whichever shutdown API is available.
//
if(pfnSetSystemPowerState != NULL)
{
RETAILMSG(1,(TEXT("PBT: Signalling power manager to suspend...\r\n")));
pfnSetSystemPowerState(NULL, POWER_STATE_SUSPEND, POWER_FORCE);
} else {
RETAILMSG(1,(TEXT("PBT: Suspending by calling PowerOffSystem...\r\n")));
PowerOffSystem();
}
//
// Acquiesce to other threads since our work is complete as of
// the call to PowerOffSystem, or the signalling of the power
// manager.
//
Sleep(0);
}
else
RETAILMSG(1,(TEXT("PBT: Button held too long (ignored)\r\n")));
}
else
RETAILMSG(1,(TEXT("PBT: Feeble button press or noise triggered it (ignored)\r\n")));
InterruptDone(PwrButtonSysIntr);
}
}
static DWORD
ResetButtonIntrThread(PVOID pArg)
{
EnableResetButtonInterrupt();
ResetButtonIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
//
// Request a SYSINTR value from the OAL.
//
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &ResetButtonIrq, sizeof ResetButtonIrq, &ResetButtonSysIntr, sizeof ResetButtonSysIntr, NULL))
{
RETAILMSG(1, (TEXT("PBT: Error! Failed to request sysintr value for reset button interrupt.\r\n")));
return(0);
}
if (!(InterruptInitialize(ResetButtonSysIntr, ResetButtonIntrEvent, 0, 0)))
{
RETAILMSG(1, (TEXT("ERROR: ResetButton: Interrupt initialize failed.\r\n")));
}
// Handle power button presses.
for (;;)
{
WaitForSingleObject(ResetButtonIntrEvent, INFINITE);
//Mask the storage device interrupt EINT11 so we don't service it before reboot is finished
s2410INT->INTMSK = (s2410INT->INTMSK | (0x1 << 0x5));
if (ResetButtonIsPushed()) // Guard against noise triggering an interrupt.
{
//
// Soft reset and standard suspend-resume both start with suspend for now.
// Call whichever shutdown API is available.
//
if(pfnSetSystemPowerState != NULL)
{
RETAILMSG(1,(TEXT("PBT: Signalling power manager to reset...\r\n")));
pfnSetSystemPowerState(NULL, POWER_STATE_RESET, POWER_FORCE);
} else {
RETAILMSG(1,(TEXT("PBT: Resetting by calling KernelIoControl(IOCTL_HAL_REBOOT)...\r\n")));
KernelIoControl(IOCTL_HAL_REBOOT,NULL,0,NULL,0,NULL);
}
//
// Acquiesce to other threads since our work is complete as of
// the call to PowerOffSystem, or the signalling of the power
// manager.
//
Sleep(0);
}
else
RETAILMSG(1,(TEXT("PBT: Feeble button press or noise triggered it (ignored)\r\n")));
InterruptDone(ResetButtonSysIntr);
}
}
DWORD
PBT_Init(DWORD dwContext)
{
DWORD IDPowerButtonThread;
DWORD IDResetButtonThread;
HMODULE hmCore;
//
// Obtain a pointer to the power manager function "SetSystemPowerState"
// from the core library so we can call into it.
//
pfnSetSystemPowerState = NULL;
hmCore = (HMODULE) LoadLibrary(_T("coredll.dll"));
if(hmCore != NULL)
{
pfnSetSystemPowerState = (PFN_SetSystemPowerState) GetProcAddress(hmCore, _T("SetSystemPowerState"));
if(pfnSetSystemPowerState == NULL)
{
FreeLibrary(hmCore);
}
}
// Initialize addresses now as opposed to when interrupts are handled so there are no race conditions
InitializeAddresses();
// Create a thread to handle the power button event, and one to handle the reset button event.
ResetButtonIntrThreadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) ResetButtonIntrThread, 0, 0, &IDResetButtonThread);
if (ResetButtonIntrThreadHandle == 0)
{
RETAILMSG(1, (TEXT("PBT: CreateThread() Fail\r\n")));
}
PowerButtonIntrThreadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) PowerButtonIntrThread, 0, 0, &IDPowerButtonThread);
if (PowerButtonIntrThreadHandle == 0)
{
RETAILMSG(1, (TEXT("PBT: CreateThread() Fail\r\n")));
}
return (dwContext);
}
BOOL WINAPI
DllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls((HMODULE) hInstDll);
break;
}
return (TRUE);
}
BOOL
PBT_Close(DWORD Handle)
{
return (TRUE);
}
//
// Device deinit - devices are expected to close down.
// The device manager does not check the return code.
//
BOOL
PBT_Deinit(DWORD dwContext)
{
return (TRUE);
}
//
// Returns handle value for the open instance.
//
DWORD
PBT_Open(DWORD dwData, DWORD dwAccess, DWORD dwShareMode)
{
return 0;
}
//
// I/O Control function - None implemented in this driver.
//
BOOL
PBT_IOControl(
DWORD Handle,
DWORD dwIoControlCode,
PBYTE pInBuf,
DWORD nInBufSize,
PBYTE pOutBuf,
DWORD nOutBufSize,
PDWORD pBytesReturned
)
{
return FALSE;
}
DWORD
PBT_Read(DWORD Handle, LPVOID pBuffer, DWORD dwNumBytes)
{
return (0);
}
DWORD
PBT_Write(DWORD Handle, LPCVOID pBuffer, DWORD dwNumBytes)
{
return (0);
}
DWORD
PBT_Seek(DWORD Handle, LONG lDistance, DWORD dwMoveMethod)
{
return (0);
}
VOID
PBT_PowerUp(VOID)
{
return;
}
VOID
PBT_PowerDown(VOID)
{
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -