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