?? eintkey.c
字號:
/****************************************Copyright (c)**************************************************
** Guangzhou ZHIYUAN electronics Co.,LTD.
**
** http://www.zyinside.com
**
**--------------File Info-------------------------------------------------------------------------------
** File Name: EINTKey.c
** Last modified Date: 2006-08-11
** Last Version: V1.0
** Description: This driver uses EINT4 button(KEY1) On MagicARM2410
**
**------------------------------------------------------------------------------------------------------
** Created By: MingYuan Zheng 鄭明遠
** Created date: 2006-08-11
** Version: V1.0
** Descriptions: The original version
**
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Description:
**
********************************************************************************************************/
#include <windows.h>
#include <types.h>
#include <excpt.h>
#include <tchar.h>
#include <cardserv.h>
#include <cardapi.h>
#include <tuple.h>
#include <devload.h>
#include <diskio.h>
#include <nkintr.h>
#include <windev.h>
#include <s3c2410x.h>
#include "EINTKey.h"
#define PRIVATE static
#define PUBLIC
/* 讀按鍵事件*/
PRIVATE HANDLE gReadKeyEvent[2];
/* 按鍵按下中斷事件 */
PRIVATE HANDLE gWaitEvent;
/* 是否退出中斷服務線程 */
PRIVATE UINT32 g_bKillIST = FALSE;
/* 中斷處理線程 */
PRIVATE HANDLE gEINTIntrThread;
/* 驅動打開計數器 */
PRIVATE UINT32 gOpenCount = 0;
/* EINT4 的物理中斷號及邏輯中斷號 */
PRIVATE UINT32 g_EINTIrq = IRQ_EINT4;
PRIVATE UINT32 g_EINTSysIntr = SYSINTR_UNDEFINED;
/* GPIO 寄存器對應的虛擬地址 */
PRIVATE volatile S3C2410X_IOPORT_REG * v_pIOPregs;
/*******************************************************************************************
函數名稱: EINT_ConfigInterruptPin
描 述: 配置外部中斷引腳并使能為 下降 沿觸發
輸入參數: 無
輸出參數: 無
返 回: 無
********************************************************************************************/
PRIVATE VOID EINT_ConfigInterruptPin(VOID)
{
v_pIOPregs->GPFCON &= ~(0x3 << 8); /* Set EINT4(GPF4) as EINT4 */
v_pIOPregs->GPFCON |= (0x2 << 8);
v_pIOPregs->EXTINT0 &= ~(0x7 << 16); /* Configure EINT4 as falling edge tiggered Mode */
v_pIOPregs->EXTINT0 |= (0x2 << 16);
}
/*******************************************************************************************
函數名稱: EINT_ConfigPinDefault
描 述: 配置外部中斷引腳恢復為輸入引腳
輸入參數: 無
輸出參數: 無
返 回: 無
********************************************************************************************/
PRIVATE VOID EINT_ConfigPinDefault(VOID)
{
v_pIOPregs->GPFCON &= ~(0x3 << 8); /* Set EINT4(GPF4) as GPIO(IN) */
}
/*******************************************************************************************
函數名稱: Key_IsPushed
描 述: 查詢按鍵是否已按下
輸入參數: 無
輸出參數: 無
返 回: FALSE: 按鍵未按下 TRUE: 按鍵已按下
*******************************************************************************************/
PRIVATE BOOL Key_IsPushed(VOID)
{
return ((v_pIOPregs->GPFDAT & (1 << 4)) ? FALSE : TRUE);
}
/*******************************************************************************************
函數名稱: EINT_InitializeAddresses
描 述: 取得相關寄存器的虛擬地址
輸入參數: 無
輸出參數: 無
返 回: > 0 分配得到的虛擬地址; FALSE: 分配失敗
*******************************************************************************************/
PRIVATE BOOL EINT_InitializeAddresses(VOID)
{
BOOL RetValue = TRUE;
RETAILMSG(1, (TEXT(">>> EINT_initalization address..set..\r\n")));
/* IO Register Allocation */
v_pIOPregs = (volatile S3C2410X_IOPORT_REG *)VirtualAlloc(0, sizeof(S3C2410X_IOPORT_REG), MEM_RESERVE, PAGE_NOACCESS);
if (v_pIOPregs == NULL)
{
ERRORMSG(1,(TEXT("For IOPregs : VirtualAlloc failed!\r\n")));
RetValue = FALSE;
}
else
{
if (!VirtualCopy((PVOID)v_pIOPregs, (PVOID)(S3C2410X_BASE_REG_PA_IOPORT >> 8), sizeof(S3C2410X_IOPORT_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
{
ERRORMSG(1,(TEXT("For IOPregs: VirtualCopy failed!\r\n")));
RetValue = FALSE;
}
}
if (!RetValue)
{
RETAILMSG (1, (TEXT("::: EINT_InitializeAddresses - Fail!!\r\n") ));
if (v_pIOPregs)
{
VirtualFree((PVOID) v_pIOPregs, 0, MEM_RELEASE);
}
v_pIOPregs = NULL;
}
else
RETAILMSG (1, (TEXT("::: EINT_InitializeAddresses - Success\r\n") ));
return(RetValue);
}
/*******************************************************************************************
函數名稱: EINTKey_IntrThread
描 述: 外部中斷按鍵服務線程
輸入參數: PVOID pArg: 線程輸入參數
輸出參數: 無
返 回: 1 或 0
*******************************************************************************************/
DWORD EINTKey_IntrThread(PVOID pArg)
{
DWORD ret;
// 創建外部中斷中斷事件
gWaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
// 初始化外部按鍵中斷: 注冊中斷事件, 允許外部中斷
if (!(InterruptInitialize(g_EINTSysIntr, gWaitEvent, 0, 0)))
{
RETAILMSG(1, (TEXT("ERROR: EINTKey: InterruptInitialize failed.\r\n")));
CloseHandle(gWaitEvent);
return 0;
}
// 外部按鍵中斷線程開始運行
while (1)
{
ret = WaitForSingleObject(gWaitEvent, INFINITE);
if ((ret == WAIT_OBJECT_0) && (g_bKillIST == FALSE))
{
if (Key_IsPushed())
{
Sleep(20); /* 延時 20ms 用于濾去噪聲 */
if (Key_IsPushed()) /* 外部中斷按鍵確實已按下 */
{
SetEvent(gReadKeyEvent[0]); /* 通知讀函數, 外部中斷按鍵按鍵按下 */
RETAILMSG(1, (TEXT("::: The Key1 Pushed. \r\n")));
}
}
}
else
{
CloseHandle(gWaitEvent);
RETAILMSG(1, (TEXT("::: EINTKey_IntrThread Exit. \r\n")));
return 0;
} //if (ret != WAIT_OBJECT_0) or Error occurs
InterruptDone(g_EINTSysIntr); /* 通知內核: 中斷處理結束 */
}
return 1;
}
/*******************************************************************************************
函數名稱: KEY_Init
描 述: 驅動程序初始化函數
輸入參數: DWORD dwContext: 設備管理器傳遞給本驅動的參數, 通常為流接口驅動在注冊表內的位置
輸出參數: 無
返 回: 驅動程序句柄
*******************************************************************************************/
PUBLIC DWORD KEY_Init(DWORD dwContext)
{
DWORD IDThread;
// 取得 GPIO 相關寄存器的虛擬地址空間
if (EINT_InitializeAddresses() == FALSE)
return 0;
// 使能 EINT4 引腳為中斷引腳, 并為下降沿觸發
EINT_ConfigInterruptPin();
// 從 OAL 請求一個 SYSINTR 值
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &g_EINTIrq, sizeof(UINT32), &g_EINTSysIntr, sizeof(UINT32), NULL))
{
RETAILMSG(1, (TEXT("ERROR: EINTKey: Failed to request sysintr value for EINT interrupt.\r\n")));
return(0);
}
RETAILMSG(1,(TEXT("INFO: EINTKey: Mapped Irq 0x%x to SysIntr 0x%x.\r\n"), g_EINTIrq, g_EINTSysIntr));
// 創建一個外部中斷處理線程 IST
gEINTIntrThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) EINTKey_IntrThread, 0, 0, &IDThread);
if (gEINTIntrThread == NULL)
{
RETAILMSG(1, (TEXT("::: KEY_Init: CreateThread() Fail.\r\n")));
KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &g_EINTSysIntr, sizeof(UINT32), NULL, 0, NULL);
return 0;
}
gReadKeyEvent[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
gReadKeyEvent[1] = CreateEvent(NULL, FALSE, FALSE, NULL);
RETAILMSG(1, (TEXT("::: KEY_Init Sucessfully! \r\n")));
// 返回不為0的數
return (DWORD)gEINTIntrThread;
}
/*******************************************************************************************
函數名稱: DllEntry
描 述: 驅動程序動態庫入口
輸入參數:
輸出參數:
返 回:
*******************************************************************************************/
PUBLIC BOOL WINAPI
DllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved)
{
switch ( dwReason )
{
case DLL_PROCESS_ATTACH:
RETAILMSG(1, (TEXT("Key: DLL_PROCESS_ATTACH. \r\n")));
DisableThreadLibraryCalls((HMODULE) hInstDll);
break;
case DLL_PROCESS_DETACH:
RETAILMSG(1, (TEXT("Key: DLL_PROCESS_DETACH. \r\n")));
break;
}
return (TRUE);
}
/*******************************************************************************************
函數名稱: KEY_Close
描 述: 驅動程序關閉函數
輸入參數: DWORD Handle:驅動程序句柄
輸出參數: 無
返 回: FALSE: 失敗 TRUE: 成功
*******************************************************************************************/
BOOL KEY_Close(DWORD Handle)
{
if (gOpenCount > 0)
SetEvent(gReadKeyEvent[1]); /* 通知調用讀函數的線程, 驅動已經關閉 */
gOpenCount = 0;
return TRUE;
} // KEY_Close
/*******************************************************************************************
函數名稱: KEY_Deinit
描 述: 驅動程序卸載函數
輸入參數: DWORD dwContext: 驅動程序句柄
輸出參數: 無
返 回: FALSE: 失敗 TRUE: 成功
*******************************************************************************************/
BOOL KEY_Deinit(DWORD dwContext)
{
SetEvent(gWaitEvent); /* 通知中斷服務線程退出 */
g_bKillIST = TRUE;
Sleep(200); /* 等待中斷服務線程退出 */
SetEvent(gReadKeyEvent[1]); /* 通知調用讀函數的線程, 驅動已經關閉 */
// 釋放中斷資源
InterruptDone(g_EINTSysIntr);
InterruptDisable(g_EINTSysIntr);
KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &g_EINTSysIntr, sizeof(UINT32), NULL, 0, NULL);
// 恢復外部中斷引腳為輸入 GPIO
EINT_ConfigPinDefault();
// 釋放申請的虛擬空間
if (v_pIOPregs)
VirtualFree((PVOID) v_pIOPregs, 0, MEM_RELEASE);
gOpenCount = 0;
CloseHandle(gReadKeyEvent[0]); /* 關閉相關事件 */
CloseHandle(gReadKeyEvent[1]);
return TRUE;
} // KEY_Deinit
/*******************************************************************************************
函數名稱: KEY_Open
描 述: 打開驅動程序
輸入參數: DWORD dwData : 驅動程序引用事例句柄
DWORD dwAccess : 訪問請求代碼,是讀和寫的組合
DWORD dwShareMode: 共享模式
輸出參數:
返 回: 驅動程序引用事例句柄
*******************************************************************************************/
DWORD KEY_Open(DWORD dwData, DWORD dwAccess, DWORD dwShareMode)
{
if (gOpenCount > 0)
return 0; // 本驅動只允許單一訪問
gOpenCount = 1;
return gOpenCount;
} // KEY_Open
/*******************************************************************************************
函數名稱: KEY_IOControl
描 述: 驅動程序 I/O 請求
輸入參數:
輸出參數:
返 回: 本驅動不支持該請求,返回 FALSE
*******************************************************************************************/
BOOL
KEY_IOControl(
DWORD Handle,
DWORD dwIoControlCode,
PBYTE pInBuf,
DWORD nInBufSize,
PBYTE pOutBuf,
DWORD nOutBufSize,
PDWORD pBytesReturned
)
{
return FALSE;
} // KEY_IOControl
/*******************************************************************************************
函數名稱: KEY_Read
描 述: 讀取按鍵狀態
輸入參數: DWORD Handle : 驅動程序引用事例句柄
LPVOID pBuffer : 接收緩沖區
DWORD dwNumBytes: 要讀的字節數
輸出參數: 無
返 回: 實際讀到字節數
*******************************************************************************************/
DWORD KEY_Read(DWORD Handle, LPVOID pBuffer, DWORD dwNumBytes)
{
DWORD ret;
uchar *pReadBuffer;
if ((pBuffer == NULL) || (dwNumBytes <= 0))
return 0;
pReadBuffer = MapPtrToProcess(pBuffer, GetCallerProcess());
*pReadBuffer = 0;
/* 掛起當前線程,直到 KEY1 按鍵按下或驅動關閉 */
ret = WaitForMultipleObjects(2, gReadKeyEvent, FALSE, INFINITE);
if (ret == WAIT_OBJECT_0)
{
ResetEvent(gReadKeyEvent[0]);
*pReadBuffer = 1; /* 按鍵按下 */
return 1;
}
else if(ret == (WAIT_OBJECT_0 + 1))
{
ResetEvent(gReadKeyEvent[1]);
*pReadBuffer = 0; /* 驅動關閉 */
return 1;
}
return 0;
} // KEY_Read
/*******************************************************************************************
函數名稱: KEY_Write
描 述: 寫函數,本驅動不支持
輸入參數:
輸出參數:
返 回:
*******************************************************************************************/
DWORD KEY_Write(DWORD Handle, LPCVOID pBuffer, DWORD dwNumBytes)
{
return 0;
} // KEY_Write
/*******************************************************************************************
函數名稱: KEY_Seek
描 述: 對設備的數據指針進行操作,本驅動不支持該函數
輸入參數:
輸出參數:
返 回:
*******************************************************************************************/
DWORD KEY_Seek(DWORD Handle, long lDistance, DWORD dwMoveMethod)
{
return 0;
} // KEY_Seek
/*******************************************************************************************
函數名稱: KEY_PowerUp
描 述: 電源上電驅動處理函數
輸入參數:
輸出參數:
返 回: 無
*******************************************************************************************/
void KEY_PowerUp(void)
{
return;
} // KEY_PowerUp
/*******************************************************************************************
函數名稱: KEY_PowerDown
描 述: 電源下電驅動處理函數
輸入參數:
輸出參數:
返 回: 無
*******************************************************************************************/
void
KEY_PowerDown(void)
{
return;
} // KEY_PowerDown
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -