📄 ch365dll.c
字号:
// 2003.08.10
// 2003.12.08 V1.2
// 2004.05.08 V1.3
//****************************************
//** Copyright (C) W.ch 1999-2004 **
//** Web: http://www.winchiphead.com **
//****************************************
//** DLL for PCI interface chip CH365 **
//** C, VC5.0 **
//****************************************
//
// PCI总线接口芯片CH365的应用层接口库 V1.3
// 南京沁恒电子有限公司 作者: W.ch 2004.05
// CH365-DLL V1.3 , Support: IO/MEM/INT
// 运行环境: Windows 98/ME, Windows 2000/XP
//
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <setupapi.h>
#include <winioctl.h>
#include "CH365DLL.H"
BOOL WINAPI DLLMain( // 动态链接库的入口
HINSTANCE iInstance,
ULONG iReason,
LPVOID iReserved );
ULONG WINAPI dllInterruptThread( // 中断模拟线程
LPVOID iParameter );
#define mTHIS_VERSION 0x13 // 当前版本
static const GUID CH365Guid = { 0x57915835, 0xa80c, 0x42cf, { 0xaf, 0xde, 0xb, 0xa0, 0xe6, 0x86, 0x4d, 0x81 } }; // GUID
HANDLE dllHandle[ mCH365_MAX_NUMBER ] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE,
INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE,
INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE,
INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; // CH365设备句柄
mPCH365_IO_REG dllIoBaseAddr[ mCH365_MAX_NUMBER ]= { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; // CH365输入输出端口基址
mPCH365_MEM_REG dllMemBaseAddr[ mCH365_MAX_NUMBER ] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; // CH365存储器基址
ULONG dllIntLine[ mCH365_MAX_NUMBER ] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // CH365中断号
mPCH365_INT_ROUTINE dllIntRoutine[ mCH365_MAX_NUMBER ] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; // CH365中断服务程序
ULONG dllIntThreadId[ mCH365_MAX_NUMBER ] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // CH365中断模拟线程的标识符
UCHAR dllDeviceName[ mCH365_MAX_NUMBER ][128]; // CH365设备名字符串
BOOL WINAPI DLLMain( // 动态链接库的入口
HINSTANCE iInstance,
ULONG iReason,
LPVOID iReserved )
{
return( TRUE );
}
ULONG WINAPI dllInterruptThread( // 中断模拟线程,每个需要中断功能的CH365设备都具有一个线程
LPVOID iParameter )
{
HANDLE dllHandleOverlap; // CH365设备句柄,可以执行重叠操作
BOOL mResult;
ULONG mIndex, mLength;
mWIN32_COMMAND mCommand;
OVERLAPPED mOverlapped;
mIndex = (ULONG)iParameter; // CH365设备序号
dllHandleOverlap = CreateFile( dllDeviceName[ mIndex ], GENERIC_READ | GENERIC_WRITE, // 打开设备,支持重叠操作
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL );
if ( dllHandleOverlap != INVALID_HANDLE_VALUE ) { // 打开设备成功
while ( dllIntRoutine[ mIndex ] ) { // 等待中断直到取消
mLength = sizeof( mWIN32_COMMAND );
mCommand.mFunction = mFuncWaitInterrupt; // 等待中断事件
mCommand.mAddress = NULL;
mCommand.mLength = 0;
mOverlapped.Internal = 0;
mOverlapped.InternalHigh = 0;
mOverlapped.Offset = 0;
mOverlapped.OffsetHigh = 0;
mOverlapped.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); // 初始化完成事件
mResult = DeviceIoControl( dllHandleOverlap, IOCTL_CH365_COMMAND, &mCommand, mLength, &mCommand, mLength, &mLength, &mOverlapped );
if ( mResult == FALSE && GetLastError() == ERROR_IO_PENDING ) // 操作未完成,即暂时无中断
mResult = GetOverlappedResult( dllHandleOverlap, &mOverlapped, &mLength, TRUE ); // 等待中断
if ( mResult && dllIntRoutine[ mIndex ] ) dllIntRoutine[ mIndex ](); // 发生中断事件则调用中断服务程序
if ( mResult == FALSE && dllIntRoutine[ mIndex ] ) Sleep( 5 ); // 出错则延时5毫秒
}
CloseHandle( dllHandleOverlap ); // 关闭句柄
}
dllIntThreadId[ mIndex ] = 0;
ExitThread( 0 ); // 退出
return( 0 );
}
HANDLE WINAPI CH365OpenDevice( // 打开CH365设备,返回句柄,出错则无效
BOOL iEnableMemory, // 是否需要支持存储器
BOOL iEnableInterrupt ) // 是否需要支持中断
{
return( CH365mOpenDevice( 0, iEnableMemory, iEnableInterrupt ) );
}
VOID WINAPI CH365CloseDevice( ) // 关闭CH365设备
{
CH365mCloseDevice( 0 );
}
ULONG WINAPI CH365GetVersion( ) // 获得DLL版本号,返回版本号
{
return( mTHIS_VERSION );
}
ULONG WINAPI CH365DriverCommand( // 直接传递命令给驱动程序,出错则返回0,否则返回数据长度
mPWIN32_COMMAND ioCommand ) // 命令结构的指针
// 该程序在调用后返回数据长度,并且仍然返回命令结构,如果是读操作,则数据返回在命令结构中,
// 返回的数据长度在操作失败时为0,操作成功时为整个命令结构的长度,例如读一个字节,则返回mWIN32_COMMAND_HEAD+1,
// 命令结构在调用前,分别提供:命令功能代码,起始地址(可选),存取数据的长度(可选),
// 命令结构在调用后,分别返回:操作状态代码,返回的基址(可选),后续数据的长度(可选),
// 操作状态代码是由WINDOWS定义的代码,可以参考NTSTATUS.H,
// 返回的基址只适用于下列命令:获取I/O基址,获取存储器基址,获取中断号,对于其它命令则保持输入时的起始地址
// 后续数据的长度是指读操作返回的数据长度,数据存放在随后的缓冲区中,对于写操作一般为0
{
return( CH365mDriverCommand( 0, ioCommand ) );
}
ULONG WINAPI CH365GetDrvVersion( ) // 获得驱动程序版本号,返回版本号,出错则返回0
{
ULONG mIndex;
ULONG mLength;
mWIN32_COMMAND mCommand;
mLength = sizeof( mWIN32_COMMAND );
for ( mIndex = 0; mIndex < mCH365_MAX_NUMBER; ++mIndex ) if ( dllHandle[ mIndex ] != INVALID_HANDLE_VALUE ) break; // 搜索一个有效句柄
if ( mIndex < mCH365_MAX_NUMBER ) { // 设备句柄有效
mCommand.mFunction = mFuncGetVersion;
mCommand.mLength = 0;
if ( DeviceIoControl( dllHandle[ mIndex ], IOCTL_CH365_COMMAND, &mCommand, mLength, &mCommand, mLength, &mLength, NULL ) )
return( mCommand.mBuffer[0] ); // 正常返回驱动程序的版本号
else return( 0 ); // 出错
}
else return( 0 ); // 没有有效的设备句柄,出错
}
BOOL WINAPI CH365GetIoBaseAddr( // 获取I/O端口的基址
mPCH365_IO_REG *oIoBaseAddr ) // 保存I/O端口基址的单元地址
{
return( CH365mGetIoBaseAddr( 0, oIoBaseAddr ) );
}
BOOL WINAPI CH365SetIoBaseAddr( // 设定I/O端口的基址
mPCH365_IO_REG iIoBaseAddr ) // 指定I/O端口基址
{
return( CH365mSetIoBaseAddr( 0, iIoBaseAddr ) );
}
BOOL WINAPI CH365GetMemBaseAddr( // 获取存储器的基址
mPCH365_MEM_REG *oMemBaseAddr ) // 保存存储器基址的单元地址
{
return( CH365mGetMemBaseAddr( 0, oMemBaseAddr ) );
}
BOOL WINAPI CH365SetMemBaseAddr( // 设定存储器的基址
mPCH365_MEM_REG iMemBaseAddr ) // 指定存储器基址,为0则关闭存储器,为-1则自动设定
{
return( CH365mSetMemBaseAddr( 0, iMemBaseAddr ) );
}
BOOL WINAPI CH365GetIntLine( // 获取中断号
PULONG oIntLine ) // 保存中断号的单元地址
{
return( CH365mGetIntLine( 0, oIntLine ) );
}
BOOL WINAPI CH365SetIntLine( // 设定中断号
ULONG iIntLine ) // 指定中断号,为0则关闭中断,为-1则自动检测并设定
{
return( CH365mSetIntLine( 0, iIntLine ) );
}
BOOL WINAPI CH365WaitInterrupt( ) // 等待中断事件
{
return( CH365mWaitInterrupt( 0 ) );
}
BOOL WINAPI CH365AbortWaitInt( ) // 放弃等待中断
{
return( CH365mAbortWaitInt( 0 ) );
}
BOOL WINAPI CH365SetIntRoutine( // 设定中断服务程序
mPCH365_INT_ROUTINE iIntRoutine ) // 指定中断服务程序,为NULL则取消中断服务,否则在中断时调用该程序
{
return( CH365mSetIntRoutine( 0, iIntRoutine ) );
}
BOOL WINAPI CH365ReadIntCommand( // 读取中断命令缓冲区
mPWIN32_COMMAND oCommand, // 指向一个足够大的缓冲区,用于保存读取的命令结构
ULONG iCmdIndex ) // 中断命令序号,为1或者2
{
return( CH365mReadIntCommand( 0, oCommand, iCmdIndex ) );
}
BOOL WINAPI CH365WriteIntCommand( // 写入中断命令缓冲区
mPWIN32_COMMAND iCommand, // 指向作为中断命令的命令结构
ULONG iCmdIndex ) // 中断命令序号,为1或者2
{
return( CH365mWriteIntCommand( 0, iCommand, iCmdIndex ) );
}
BOOL WINAPI CH365ReadIoByte( // 从I/O端口读取一个字节
PVOID iAddr, // 指定I/O端口的地址
PUCHAR oByte ) // 指向一个字节单元,用于保存读取的字节数据
{
return( CH365mReadIoByte( 0, iAddr, oByte ) );
}
BOOL WINAPI CH365ReadIoWord( // 从I/O端口读取一个字
PVOID iAddr, // 指定I/O端口的地址
PUSHORT oWord ) // 指向一个字单元,用于保存读取的字数据
{
return( CH365mReadIoWord( 0, iAddr, oWord ) );
}
BOOL WINAPI CH365ReadIoDword( // 从I/O端口读取一个双字
PVOID iAddr, // 指定I/O端口的地址
PULONG oDword ) // 指向一个双字单元,用于保存读取的双字数据
{
return( CH365mReadIoDword( 0, iAddr, oDword ) );
}
BOOL WINAPI CH365WriteIoByte( // 向I/O端口写入一个字节
PVOID iAddr, // 指定I/O端口的地址
UCHAR iByte ) // 待写入的字节数据
{
return( CH365mWriteIoByte( 0, iAddr, iByte ) );
}
BOOL WINAPI CH365WriteIoWord( // 向I/O端口写入一个字
PVOID iAddr, // 指定I/O端口的地址
USHORT iWord ) // 待写入的字数据
{
return( CH365mWriteIoWord( 0, iAddr, iWord ) );
}
BOOL WINAPI CH365WriteIoDword( // 向I/O端口写入一个双字
PVOID iAddr, // 指定I/O端口的地址
ULONG iDword ) // 待写入的双字数据
{
return( CH365mWriteIoDword( 0, iAddr, iDword ) );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -