www.pudn.com > GPIO.rar > gpio.c


/****************************************Copyright (c)************************************************** 
**                               Guangzhou ZHIYUAN electronics Co.,LTD. 
**                                      
**                                 http://www.zyinside.com 
** 
**--------------File Info------------------------------------------------------------------------------- 
** File Name: 				gpio.c 
** Last modified Date: 			2008-01-08 
** Last Version:			V1.0		 
** Description: 			S3C2410 GPIO  
**                           
**------------------------------------------------------------------------------------------------------ 
** Created By: 				MingYuan Zheng  
** Created date: 			2006-10-09 
** Version: 				V1.0 
** Descriptions:			The original version 
** 
**------------------------------------------------------------------------------------------------------ 
** Modified by: 
** Modified date: 
** Version: 
** Description: 
** 
********************************************************************************************************/ 
 
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
 
#include  
#include "gpio.h" 
 
 
#define PRIVATE			static 
#define PUBLIC 
 
 
/* GPIO 寄存器对应的虚拟地址 */ 
PRIVATE volatile S3C2440A_IOPORT_REG * v_pIOPregs; 
 
PRIVATE g_OpenCount = 0;			/* 驱动打开计数器 */ 
 
#define  ADDRESS_INTERVAL_GPIO		0x04 
#define  GPx_GPA					0 
#define  GPx_GPJ					d 
 
 
/******************************************************************************************* 
函数名称: PIO_InitializeAddresses 
描    述: 取得相关寄存器的虚拟地址 
输入参数: 无 
输出参数: 无 
返    回: > 0 分配到的虚拟地址;  FALSE: 失败  
*******************************************************************************************/ 
PRIVATE BOOL PIO_InitializeAddresses(void) 
{ 
	BOOL	RetValue = TRUE; 
 
	//	IO Register Allocation 
	v_pIOPregs = (volatile S3C2440A_IOPORT_REG *)VirtualAlloc(0, sizeof(S3C2440A_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)(S3C2440A_BASE_REG_PA_IOPORT >> 8), sizeof(S3C2440A_IOPORT_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))  
		{ 
			ERRORMSG(1,(TEXT("For IOPregs: VirtualCopy failed!\r\n"))); 
			RetValue = FALSE; 
		} 
	} 
	 
	if (!RetValue)  
	{ 
		RETAILMSG (1, (TEXT("::: PIO_InitializeAddresses - Fail!!\r\n") )); 
 
		if (v_pIOPregs)  
		{ 
			VirtualFree((PVOID) v_pIOPregs, 0, MEM_RELEASE); 
		} 
 
		v_pIOPregs = NULL; 
 
		RetValue = FALSE; 
		return RetValue; 
	} 
 
	return(RetValue); 
} 
 
 
/******************************************************************************************* 
函数名称: PIO_Init 
描    述: 驱动程序初始化函数 
输入参数: DWORD dwContext: 设备管理器传递给本驱动的参数, 通常为流接口驱动在注册表内的位置 	 
输出参数: 无 
返    回: 驱动程序句柄 
*******************************************************************************************/ 
PUBLIC DWORD PIO_Init(DWORD dwContext) 
{ 
	RETAILMSG(1,(TEXT("GPIO Initialize\r\n"))); 
	PIO_InitializeAddresses(); 
	g_OpenCount = 0; 
 
	return (DWORD)1; 
} 
 
 
/******************************************************************************************* 
函数名称: DllEntry 
描    述: 驱动程序动态库入口 
输入参数: 	 
输出参数: 
返    回:  
*******************************************************************************************/ 
PUBLIC BOOL WINAPI 
DllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved) 
{ 
    switch ( dwReason )  
	{ 
		case DLL_PROCESS_ATTACH: 
			RETAILMSG(1, (TEXT("PIO: DLL_PROCESS_ATTACH\r\n"))); 
			DisableThreadLibraryCalls((HMODULE) hInstDll); 
			break; 
 
		case DLL_PROCESS_DETACH: 
			RETAILMSG(1, (TEXT("PIO: DLL_PROCESS_DETACH\r\n"))); 
			break; 
    } 
    return (TRUE); 
} 
 
 
/******************************************************************************************* 
函数名称: PIO_Close 
描    述: 驱动程序关闭函数 
输入参数: DWORD Handle:驱动程序引用事例句柄 
输出参数: 无 
返    回: FALSE: 失败    TRUE: 成功  
*******************************************************************************************/ 
BOOL PIO_Close(DWORD Handle) 
{ 
	g_OpenCount = 0; 
 
    return TRUE; 
} 
 
 
/******************************************************************************************* 
函数名称: PIO_Deinit 
描    述: 驱动程序卸载函数 
输入参数: DWORD dwContext: 驱动程序句柄 
输出参数: 无 
返    回: FALSE: 失败    TRUE: 成功 
*******************************************************************************************/ 
BOOL PIO_Deinit(DWORD dwContext) 
{ 
	g_OpenCount = 0; 
 
	if (v_pIOPregs) 
		VirtualFree((PVOID) v_pIOPregs, 0, MEM_RELEASE);	/* 释放申请的虚拟空间 */ 
 
    return TRUE; 
} 
 
 
/******************************************************************************************* 
函数名称: PIO_Open 
描    述: 打开驱动程序 
输入参数: DWORD dwData     : 设备驱动程序句柄 
          DWORD dwAccess   : 访问请求代码,是读和写的组合 
          DWORD dwShareMode: 共享模式   
输出参数: 
返    回: 驱动程序引用事例句柄 
*******************************************************************************************/ 
DWORD PIO_Open(DWORD dwData, DWORD dwAccess, DWORD dwShareMode) 
{ 
	if (g_OpenCount > 0) 
		return 0; 
 
	g_OpenCount++; 
 
    return g_OpenCount;							/* 返回一个不为零的数 */ 
} 
 
 
 
// 定义 S3C2410 GPA ~ GPH 引脚个数  
						//  A   B    C   D   E  F  G   H    J 
const BYTE PinNumTbl[14] = {23, 11, 16, 16, 16, 8, 16, 11,0,0,0,0,0,13}; 
 
 
/******************************************************************************************* 
函数名称: GPIO_SetPinOut 
描    述: 设置某个引脚为输出引脚 
输入参数: DWORD dwIoControlCode : I/O control code, 指出操作的GPIO组, 如GPA, GPB 
          BYTE PinNum			: 引脚编号, 如 GPB1, 则值为 1 
输出参数: 
返    回: TRUE: 操作成功    FALSE: 操作失败 
*******************************************************************************************/ 
BOOL GPIO_SetPinOut(DWORD dwIoControlCode, BYTE PinNum) 
{ 
	DWORD GPx; 
	volatile DWORD *pRegCON;						// GPxCON's address 
 
	GPx = dwIoControlCode & IOCTL_GPX_MASK; 
	if (PinNum >= PinNumTbl[GPx])  return FALSE; 
 
	pRegCON = (DWORD *)v_pIOPregs + GPx * ADDRESS_INTERVAL_GPIO; 
 
	if (GPx != GPx_GPA) 
	{ 
		*pRegCON &= ~(0x03 << (PinNum * 2)); 
		*pRegCON |=  (0x01 << (PinNum * 2)); 
	} 
	 
	else 
		*pRegCON &= ~(0x01 << PinNum); 
 
	return TRUE; 
} 
 
 
/******************************************************************************************* 
函数名称: GPIO_SetMultiPinOut 
描    述: 设置多个引脚为输出引脚 
输入参数: DWORD dwIoControlCode : I/O control code, 指出操作的GPIO组, 如GPA, GPB 
          BYTE PinNum			: 引脚编号掩码, 如操作 GPB1,GPB3, 则值为: (0x01 << 1) + (0x01 << 3) 
输出参数: 
返    回: TRUE: 操作成功    FALSE: 操作失败 
*******************************************************************************************/ 
BOOL GPIO_SetMultiPinOut(DWORD dwIoControlCode, DWORD PinMask) 
{ 
	DWORD GPx, i; 
	volatile DWORD *pRegCON;			// GPXCON's address 
 
	GPx = dwIoControlCode & IOCTL_GPX_MASK; 
	pRegCON = (DWORD *)v_pIOPregs + GPx * ADDRESS_INTERVAL_GPIO; 
	 
	for (i = 0; i < PinNumTbl[GPx]; i++) 
	{ 
		if (PinMask & (0x01 << i)) 
		{ 
			if (GPx != GPx_GPA) 
			{ 
				*pRegCON &= ~(0x03 << (i * 2)); 
				*pRegCON |=  (0x01 << (i * 2)); 
			} 
			else 
				*pRegCON &= ~(0x01 << i); 
		} 
	} 
 
	return TRUE; 
} 
 
 
/******************************************************************************************* 
函数名称: GPIO_SetPinIn 
描    述: 设置某个引脚为输入引脚 
输入参数: DWORD dwIoControlCode : I/O control code, 指出操作的GPIO组, 如GPA, GPB 
          BYTE PinNum			: 引脚编号, 如 GPB1, 则值为 1 
输出参数: 
返    回: TRUE: 操作成功    FALSE: 操作失败 
*******************************************************************************************/ 
BOOL GPIO_SetPinIn(DWORD dwIoControlCode, BYTE PinNum) 
{ 
	DWORD GPx; 
	volatile DWORD *pRegCON;				    // GPXCON's address 
 
	GPx = dwIoControlCode & IOCTL_GPX_MASK; 
 
	if (GPx == GPx_GPA)	 return FALSE;			// GPA  output only 
	if (PinNum >= PinNumTbl[GPx])  return FALSE; 
 
	pRegCON = (DWORD *)v_pIOPregs + GPx * ADDRESS_INTERVAL_GPIO; 
	RETAILMSG(1,(TEXT( "GPIO_SetPinIn() GPx = 0x%x   v_pIOPregs = 0x%x pRegCON = 0x%x\r\n"),GPx,v_pIOPregs,pRegCON)); 
	PinNum = PinNum * 2; 
	*pRegCON &= ~(0x03 << PinNum); 
 
	return TRUE; 
} 
 
 
/******************************************************************************************* 
函数名称: GPIO_SetMultiPinIn 
描    述: 设置多个引脚为输入引脚 
输入参数: DWORD dwIoControlCode : I/O control code, 指出操作的GPIO组, 如GPA, GPB 
          BYTE PinNum			: 引脚编号掩码, 如操作 GPB1,GPB3, 则值为: (0x01 << 1) + (0x01 << 3) 
输出参数: 
返    回: TRUE: 操作成功    FALSE: 操作失败 
*******************************************************************************************/ 
BOOL GPIO_SetMultiPinIn(DWORD dwIoControlCode, DWORD PinMask) 
{ 
	DWORD GPx, i; 
	volatile DWORD *pRegCON;					// GPXCON's address 
 
	GPx = dwIoControlCode & IOCTL_GPX_MASK; 
	if (GPx == GPx_GPA)	 return FALSE;			// GPA  output only 
 
	pRegCON = (DWORD *)v_pIOPregs + GPx * ADDRESS_INTERVAL_GPIO; 
	 
	for (i = 0; i < PinNumTbl[GPx]; i++) 
	{ 
		if (PinMask & (0x01 << i)) 
			*pRegCON &= ~(0x03 << (i * 2)); 
	} 
 
	return TRUE; 
} 
 
 
/******************************************************************************************* 
函数名称: GPIO_SetPin 
描    述: 设置某个引脚输出高电平 
输入参数: DWORD dwIoControlCode : I/O control code, 指出操作的GPIO组, 如GPA, GPB 
          BYTE PinNum			: 引脚编号, 如 GPB1, 则值为 1 
输出参数: 
返    回: TRUE: 操作成功    FALSE: 操作失败 
*******************************************************************************************/ 
BOOL GPIO_SetPin(DWORD dwIoControlCode, BYTE PinNum) 
{ 
	DWORD GPx; 
	volatile DWORD *pRegDAT;			// GPxDAT's address 
 
	GPx = dwIoControlCode & IOCTL_GPX_MASK; 
	if (PinNum >= PinNumTbl[GPx])  return FALSE; 
	 
	pRegDAT = ((DWORD *)v_pIOPregs + GPx * ADDRESS_INTERVAL_GPIO + 1); 
	*pRegDAT |=  (0x01 << PinNum); 
 
	return TRUE; 
} 
 
 
/******************************************************************************************* 
函数名称: GPIO_SetAllPin 
描    述: 设置多个引脚输出高电平 
输入参数: DWORD dwIoControlCode : I/O control code, 指出操作的GPIO组, 如GPA, GPB 
          BYTE PinNum			: 引脚编号掩码, 如操作 GPB1,GPB3, 则值为: (0x01 << 1) + (0x01 << 3) 
输出参数: 
返    回: TRUE: 操作成功    FALSE: 操作失败 
*******************************************************************************************/ 
BOOL GPIO_SetAllPin(DWORD dwIoControlCode, DWORD PinMask) 
{ 
	DWORD GPx, i; 
	volatile DWORD *pRegDAT;			// GPxDAT's address 
 
	GPx = dwIoControlCode & IOCTL_GPX_MASK; 
	pRegDAT = ((DWORD *)v_pIOPregs + GPx * ADDRESS_INTERVAL_GPIO + 1); 
 
	for (i = 0; i < PinNumTbl[GPx]; i++) 
	{ 
		if (PinMask & (0x01 << i)) 
			*pRegDAT |= (0x01 << i); 
	} 
 
	return TRUE; 
} 
 
 
/******************************************************************************************* 
函数名称: GPIO_ClrPin 
描    述: 设置某个引脚输出低电平 
输入参数: DWORD dwIoControlCode : I/O control code, 指出操作的GPIO组, 如GPA, GPB 
          BYTE PinNum			: 引脚编号, 如 GPB1, 则值为 1 
输出参数: 
返    回: TRUE: 操作成功    FALSE: 操作失败 
*******************************************************************************************/ 
BOOL GPIO_ClrPin(DWORD dwIoControlCode, BYTE PinNum) 
{ 
	DWORD GPx; 
	volatile DWORD *pRegDAT;			// GPxDAT's address 
 
	GPx = dwIoControlCode & IOCTL_GPX_MASK; 
	if (PinNum >= PinNumTbl[GPx])  return FALSE; 
 
	pRegDAT = ((DWORD *)v_pIOPregs + GPx * ADDRESS_INTERVAL_GPIO + 1);				// 1 is a DWORD pointer 
	*pRegDAT &= ~(0x01 << PinNum); 
 
	return TRUE; 
} 
 
 
/******************************************************************************************* 
函数名称: GPIO_ClrAllPin 
描    述: 设置多个引脚输出低电平 
输入参数: DWORD dwIoControlCode : I/O control code, 指出操作的GPIO组, 如GPA, GPB 
          BYTE PinNum			: 引脚编号掩码, 如操作 GPB1,GPB3, 则值为: (0x01 << 1) + (0x01 << 3) 
输出参数: 
返    回: TRUE: 操作成功    FALSE: 操作失败 
*******************************************************************************************/ 
BOOL GPIO_ClrAllPin(DWORD dwIoControlCode, DWORD PinMask) 
{ 
	DWORD GPx, i; 
	volatile DWORD *pRegDAT;			// GPxDAT's address 
 
	GPx = dwIoControlCode & IOCTL_GPX_MASK; 
	pRegDAT = (DWORD *)v_pIOPregs + GPx * ADDRESS_INTERVAL_GPIO + 1; 
 
	for (i = 0; i < PinNumTbl[GPx]; i++) 
	{ 
		if (PinMask & (0x01 << i)) 
			*pRegDAT &= ~(0x01 << i); 
	} 
 
	return TRUE; 
} 
 
 
/******************************************************************************************* 
函数名称: GPIO_ReadPin 
描    述: 读取某个引脚的电平状态 
输入参数: DWORD dwIoControlCode : I/O control code, 指出操作的GPIO组, 如GPA, GPB 
          BYTE PinNum			: 引脚编号, 如 GPB1, 则值为 1 
输出参数: YTE *pValue			: 1: 引脚电平为高;  0: 引脚电平为低 
返    回: TRUE: 操作成功    FALSE: 操作失败 
*******************************************************************************************/ 
BOOL GPIO_ReadPin(DWORD dwIoControlCode, BYTE PinNum, BYTE *pValue) 
{ 
	DWORD GPx; 
	volatile DWORD *pRegDAT;						// GPxDAT's address 
 
	if (pValue == NULL)  return FALSE; 
 
	GPx = dwIoControlCode & IOCTL_GPX_MASK; 
	if (GPx == GPx_GPA)	 return FALSE;				// GPA  output only 
 
	pRegDAT = ((DWORD *)v_pIOPregs + GPx * ADDRESS_INTERVAL_GPIO + 1);				// 1 is a DWORD pointer 
	if (*pRegDAT & (0x01 << PinNum)) 
		*pValue = 1; 
	else 
		*pValue = 0; 
 
	 
	return TRUE; 
} 
 
 
/******************************************************************************************* 
函数名称: GPIO_ReadAllPin 
描    述: 读出一组引脚的状态 
输入参数: DWORD dwIoControlCode : I/O control code, 指出操作的GPIO组, 如GPA, GPB 
          DWORD nOutBufSize		: pOutBuf 大小, 取值为1, 因为 GPA 不可读, 其它组最多超不过16个引脚 
输出参数: ushort *pOutBuf		: 整组引脚电平状态 
返    回: TRUE: 操作成功    FALSE: 操作失败 
*******************************************************************************************/ 
BOOL GPIO_ReadAllPin(DWORD dwIoControlCode, ushort *pOutBuf, DWORD nOutBufSize) 
{ 
	DWORD GPx; 
	volatile DWORD *pRegDAT;						// GPxDAT's address 
	 
	GPx = dwIoControlCode & IOCTL_GPX_MASK; 
 
	if (nOutBufSize < 1) return FALSE; 
	if (GPx == GPx_GPA)	 return FALSE;				// GPA  output only 
	 
	pRegDAT = (DWORD *)v_pIOPregs + GPx * ADDRESS_INTERVAL_GPIO + 1; 
 
	*pOutBuf = (ushort)*pRegDAT; 
	 
	return TRUE; 
} 
 
 
 
/******************************************************************************************* 
函数名称: GPIO_ConfigPullUp 
描    述: 设置某个引脚是否内部上拉 
输入参数: DWORD dwIoControlCode : I/O control code, 指出操作的GPIO组, 如GPA, GPB 
          BYTE PinNum			: 引脚编号, 如 GPB1, 则值为 1 
          BOOL bPullup			: 是否上拉, TRUE: 上拉; FALSE: 不上拉. 
输出参数: 
返    回: TRUE: 操作成功    FALSE: 操作失败 
*******************************************************************************************/ 
BOOL GPIO_ConfigPullUp(DWORD dwIoControlCode, BYTE PinNum, BOOL bPullup) 
{ 
	DWORD GPx; 
	volatile DWORD *pRegUp;							// GPxUP's address 
 
	GPx = dwIoControlCode & IOCTL_GPX_MASK; 
	if (GPx == GPx_GPA)	 return FALSE;				// GPA  output only 
 
	pRegUp = ((DWORD *)v_pIOPregs + GPx * ADDRESS_INTERVAL_GPIO + 2);		// 2 is a DWORD pointer 
	if (bPullup) 
		*pRegUp &= ~(0x01 << PinNum);				// Pull up is enable 
	else 
		*pRegUp |= (0x01 << PinNum);				// Pull up is disable 
 
	return TRUE; 
} 
 
 
/******************************************************************************************* 
函数名称: GPIO_ConfigMultiPinPullup 
描    述: 设置多个引脚是否内部上拉 
输入参数: DWORD dwIoControlCode : I/O control code, 指出操作的GPIO组, 如GPA, GPB 
          BYTE PinNum			: 引脚编号掩码, 如操作 GPB1,GPB3, 则值为: (0x01 << 1) + (0x01 << 3) 
          BOOL bPullup			: 是否上拉, TRUE: 上拉; FALSE: 不上拉. 
输出参数: 
返    回: TRUE: 操作成功    FALSE: 操作失败 
*******************************************************************************************/ 
BOOL GPIO_ConfigMultiPinPullup(DWORD dwIoControlCode, DWORD PinMask, BOOL bPullup) 
{ 
	DWORD GPx; 
	volatile DWORD *pRegUp;							// GPxUP's address 
	 
	GPx = dwIoControlCode & IOCTL_GPX_MASK; 
	if (GPx == GPx_GPA)	 return FALSE;				// GPA  output only 
	 
	pRegUp = ((DWORD *)v_pIOPregs + GPx * ADDRESS_INTERVAL_GPIO + 2);		// 2 is a DWORD pointer 
	if (bPullup) 
		*pRegUp &= ~(PinMask);						// Pull up is enable 
	else 
		*pRegUp |= (PinMask);						// Pull up is disable 
	 
	return TRUE; 
} 
 
 
/******************************************************************************************* 
函数名称: PIO_IOControl 
描    述: 驱动程序 I/O 请求 
输入参数: DWORD dwIoControlCode:  见本文件的头文件 
输出参数: 
返    回: TRUE: 操作成功    FALSE: 操作失败 
*******************************************************************************************/ 
BOOL 
PIO_IOControl( 
    DWORD Handle, 
    DWORD dwIoControlCode, 
    PBYTE pInBuf, 
    DWORD nInBufSize, 
    PBYTE pOutBuf, 
    DWORD nOutBufSize, 
    PDWORD pBytesReturned 
    ) 
{ 
	BOOL bErr = FALSE;	 
	RETAILMSG(1,(TEXT("PIO_IOControl()  dwIoControlCode =0x%x \r\n"),dwIoControlCode)); 
	switch(dwIoControlCode & IOCTL_GPIO_FUN_MASK) 
	{	 
		/* 
		*   设置引脚为输出 
		*/ 
		case IOCTL_GPIO_SET_PIN_OUT: 
			if (nInBufSize > 0) 
				bErr = GPIO_SetPinOut(dwIoControlCode, *pInBuf);	 
		break;			 
 
		case IOCTL_GPIO_SET_MULTI_PIN_OUT:                    /* pInBuf 必须为4字节 */ 
			if (nInBufSize > 0) 
         		bErr = GPIO_SetMultiPinOut(dwIoControlCode, *(DWORD *)pInBuf);	 
            //RETAILMSG(TRUE, (TEXT("*(DWORD *)pInBuf is 0x%x).\r\n"), *(DWORD *)pInBuf));  
		break; 
 
 
		/* 
		*   设置引脚为输入 
		*/ 
		case IOCTL_GPIO_SET_PIN_IN: 
			RETAILMSG(1,(TEXT("PIO_IOControl() set a pin in \r\n"))); 
			if (nInBufSize > 0) 
				bErr = GPIO_SetPinIn(dwIoControlCode, *pInBuf); 
		break; 
 
		case IOCTL_GPIO_SET_MULTI_PIN_IN:                     /* pInBuf 必须为4字节 */ 
			RETAILMSG(1,(TEXT("PIO_IOControl() set multi pin in \r\n"))); 
			if (nInBufSize > 0) 
				bErr = GPIO_SetMultiPinIn(dwIoControlCode, *(DWORD *)pInBuf); 
			//RETAILMSG(TRUE, (TEXT("*(DWORD *)pInBuf is 0x%x).\r\n"), *(DWORD *)pInBuf)); 	 
		break; 
 
 
		/*  
		*   设置引脚输出高电平 
		*/ 
		case IOCTL_GPIO_SET_PIN: 
			if (nInBufSize > 0) 
				bErr = GPIO_SetPin(dwIoControlCode, *pInBuf); 
		break; 
 
		case IOCTL_GPIO_SET_MULTI_PIN:                          /* pInBuf 必须为4字节 */ 
			if (nInBufSize >= 0) 
				bErr = GPIO_SetAllPin(dwIoControlCode, *(DWORD *)pInBuf); 
			//RETAILMSG(TRUE, (TEXT("*(DWORD *)pInBuf is 0x%x).\r\n"), *(DWORD *)pInBuf));  
		break; 
 
 
		/* 
		*   设置引脚输出低电平 
		*/ 
		case IOCTL_GPIO_CLR_PIN: 
			if (nInBufSize > 0) 
				bErr = GPIO_ClrPin(dwIoControlCode, *pInBuf); 
		break; 
 
		case IOCTL_GPIO_CLR_MULTI_PIN:                          /* pInBuf 必须为4字节 */ 
			if (nInBufSize > 0)           
				bErr = GPIO_ClrAllPin(dwIoControlCode, *(DWORD *)pInBuf); 
		    //RETAILMSG(TRUE, (TEXT("*(DWORD *)pInBuf is 0x%x).\r\n"), *(DWORD *)pInBuf));  
		break; 
 
 
		/* 
		*   读取引脚电平状态 
		*/ 
		case IOCTL_GPIO_READ_PIN: 
			RETAILMSG(1,(TEXT("GPIO READ nOutBufSize = 0x%x nInBufSize = 0x%x \r\n"),nOutBufSize,nInBufSize)); 
			if ((nOutBufSize > 0) && (nInBufSize > 0))  
			{ 
				bErr = GPIO_ReadPin(dwIoControlCode, *pInBuf, pOutBuf); 
				RETAILMSG(1,(TEXT("Pin Stuatus = 0x%x\r\n"),*pOutBuf)); 
				*pBytesReturned = 1; 
			} 
		break; 
 
		case IOCTL_GPIO_READ_ALL_PIN:                         /* pOutBuf 必须为2字节 */ 
			if (nOutBufSize > 0)    
			{ 
				bErr = GPIO_ReadAllPin(dwIoControlCode, (ushort *)pOutBuf, 1); 
				*pBytesReturned = 1; 
			} 
		break; 
 
 
		/*   
		*	使能引脚内部上拉 
		*/ 
		case IOCTL_GPIO_EN_PULLUP:							  /* *pInBuf 为1字节 */ 
			if (nInBufSize > 0)  
				bErr = GPIO_ConfigPullUp(dwIoControlCode, *pInBuf, TRUE); 
		break; 
 
		case IOCTL_GPIO_EN_MULTI_PIN_PULLUP:				  /* pInBuf 必须为4字节 */ 
			if (nInBufSize > 0)   
				bErr = GPIO_ConfigMultiPinPullup(dwIoControlCode, *(DWORD *)pInBuf, TRUE); 
		break; 
 
 
		/*    
		*	禁止引脚内部上拉 
		*/ 
		case IOCTL_GPIO_DIS_PULLUP: 
			if (nInBufSize > 0) 		  					  /* *pInBuf 为1字节 */ 
				bErr = GPIO_ConfigPullUp(dwIoControlCode, *pInBuf, FALSE); 
		break; 
 
		case IOCTL_GPIO_DIS_MULTI_PIN_PULLUP:				  /* pInBuf 必须为4字节 */ 
			if (nInBufSize > 0)   
				bErr = GPIO_ConfigMultiPinPullup(dwIoControlCode, *(DWORD *)pInBuf, FALSE); 
		break; 
 
		default: 
		break; 
	} 
 
    return bErr; 
}   // PIO_IOControl 
 
 
 
/******************************************************************************************* 
函数名称: PIO_Read 
描    述: 读取按键状态 
输入参数: DWORD Handle    : 驱动程序引用事例句柄 
          LPVOID pBuffer  : 接收缓冲区 
          DWORD dwNumBytes: 要读的字节数 
输出参数: 无 
返    回: 实际读到字节数 
*******************************************************************************************/ 
DWORD PIO_Read(DWORD Handle, LPVOID pBuffer, DWORD dwNumBytes) 
{ 
	return 0; 
} 
 
 
 
/******************************************************************************************* 
函数名称: PIO_Write 
描    述: 写函数,本驱动不支持 
输入参数:  
输出参数: 
返    回: 
*******************************************************************************************/ 
DWORD PIO_Write(DWORD Handle, LPCVOID pBuffer, DWORD dwNumBytes) 
{ 
	return 0; 
} 
 
 
/******************************************************************************************* 
函数名称: PIO_Seek 
描    述: 对设备的数据指针进行操作,本驱动不支持该函数 
输入参数:  
输出参数: 
返    回: 
*******************************************************************************************/ 
DWORD PIO_Seek(DWORD Handle, long lDistance, DWORD dwMoveMethod) 
{ 
	return 0; 
} 
 
 
/******************************************************************************************* 
函数名称: PIO_PowerUp 
描    述: 电源上电驱动处理函数 
输入参数:  
输出参数: 
返    回: 无 
*******************************************************************************************/ 
void PIO_PowerUp(void) 
{ 
	return; 
} 
 
 
/******************************************************************************************* 
函数名称: PIO_PowerDown 
描    述: 电源下电驱动处理函数 
输入参数:  
输出参数: 
返    回: 无 
*******************************************************************************************/ 
void PIO_PowerDown(void) 
{ 
	return; 
}