⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch375dll.c

📁 CH375 是南京沁恒公司开发的一个USB总线的通用接口芯片
💻 C
📖 第 1 页 / 共 2 页
字号:
// 2003.09.08, 2003.12.28, 2004.10.15
//****************************************
//**  Copyright  (C)  W.ch  1999-2004   **
//**  Web:  http://www.winchiphead.com  **
//****************************************
//**  DLL for USB interface chip CH375  **
//**  C, VC5.0                          **
//****************************************
//
// USB总线接口芯片CH375的应用层接口库  V1.2
// 南京沁恒电子有限公司  作者: W.ch 2004.10
// CH375-DLL  V1.2 , Support: Ctrl/Bulk/Int
// 运行环境: Windows 98/ME, Windows 2000/XP
// support USB chip: CH372/CH375
//

#include	<windows.h>
#include	<stdlib.h>
#include	<stdio.h>
#include	<conio.h>
#include	<setupapi.h>
#include	<winioctl.h>

#include	"CH375DLL.H"


BOOL	WINAPI	DLLMain(  // 动态链接库的入口
	HINSTANCE	iInstance,
	ULONG		iReason,
	LPVOID		iReserved );


ULONG	WINAPI	dllInterruptThread(  // 中断模拟线程
	LPVOID		iParameter );


#define		mTHIS_VERSION			0x12				// 当前版本


static const GUID CH375Guid = { 0x5e7f6bdf, 0x1ce5, 0x4d78, { 0xbb, 0xcf, 0xd2, 0xc, 0x44, 0x32, 0x9f, 0x7d } };	// GUID


HANDLE				dllHandle[ mCH375_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 };	// CH375设备句柄
mPCH375_INT_ROUTINE	dllIntRoutine[ mCH375_MAX_NUMBER ] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
														NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };	// CH375中断服务程序
ULONG				dllIntThreadId[ mCH375_MAX_NUMBER ] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };	// CH375中断模拟线程的标识符
UCHAR				dllDeviceName[ mCH375_MAX_NUMBER ][128];	// CH375设备名字符串
UCHAR				dllI2cSpeed[ mCH375_MAX_NUMBER ] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };	// CH375的I2C接口的速度设置


BOOL	WINAPI	DLLMain(  // 动态链接库的入口
	HINSTANCE	iInstance,
	ULONG		iReason,
	LPVOID		iReserved )
{
	return( TRUE );
}

ULONG	WINAPI	dllInterruptThread(  // 中断模拟线程,每个需要中断功能的CH375设备都具有一个线程
	LPVOID		iParameter )
{
	HANDLE				dllHandleOverlap;	// CH375设备句柄,可以执行重叠操作
	BOOL				mResult;
	ULONG				mIndex, mLength;
	mWIN32_COMMAND		mCommand;
	OVERLAPPED			mOverlapped;
	mIndex = (ULONG)iParameter;  // CH375设备序号
	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 ] ) {  // 等待中断直到取消
			mCommand.mFunction = mPipeInterUp;  // 从中断数据上传管道读取数据
			mCommand.mLength = mCH375_PACKET_LENGTH;  // 数据长度
			mLength = sizeof( mWIN32_COMMAND );  // 缓冲区长度,数据长度加上命令结构头的长度
			mOverlapped.Internal = 0;
			mOverlapped.InternalHigh = 0;
			mOverlapped.Offset = 0;
			mOverlapped.OffsetHigh = 0;
			mOverlapped.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );  // 初始化完成事件
			mResult = DeviceIoControl( dllHandleOverlap, IOCTL_CH375_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 ]( & mCommand.mBuffer[0] );  // 将当前的中断特征数据提供给中断服务程序
			if ( mResult == FALSE && dllIntRoutine[ mIndex ] ) Sleep( 5 );  // 出错则延时5毫秒
		}
		CloseHandle( dllHandleOverlap );  // 关闭句柄
	}
	dllIntThreadId[ mIndex ] = 0;
	ExitThread( 0 );  // 退出
	return( 0 );
}

HANDLE	WINAPI	CH375OpenDevice(  // 打开CH375设备,返回句柄,出错则无效
	ULONG			iIndex )  // 指定CH375设备序号,0对应第一个设备
{
	UCHAR								mBuffer[1024];
	LPGUID								mClassGuid;
	HDEVINFO							mDevInfo;
	SP_INTERFACE_DEVICE_DATA			mDevIfData;
	PSP_INTERFACE_DEVICE_DETAIL_DATA	mDevIfDetail;
	if ( iIndex >= mCH375_MAX_NUMBER ) return( INVALID_HANDLE_VALUE );  // 太多设备,不支持
	mClassGuid = ( LPGUID )&CH375Guid;  // 设备类
	mDevInfo = SetupDiGetClassDevs( mClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE );  // 获得指定设备类
	if ( mDevInfo == INVALID_HANDLE_VALUE ) return( INVALID_HANDLE_VALUE );
	mDevIfData.cbSize = sizeof( mDevIfData );
	if ( !SetupDiEnumDeviceInterfaces( mDevInfo, NULL, mClassGuid, iIndex, &mDevIfData ) ) {  // 枚举指定序号的设备
		SetupDiDestroyDeviceInfoList( mDevInfo );
		return( INVALID_HANDLE_VALUE );
	}
	mDevIfDetail = ( PSP_INTERFACE_DEVICE_DETAIL_DATA ) mBuffer;
	mDevIfDetail -> cbSize = sizeof( SP_INTERFACE_DEVICE_DETAIL_DATA );
	if ( !SetupDiGetDeviceInterfaceDetail( mDevInfo, &mDevIfData, mDevIfDetail, 1020, NULL, NULL ) ) {  // 获得设备详细信息
		SetupDiDestroyDeviceInfoList( mDevInfo );
		return( INVALID_HANDLE_VALUE );
	}
	lstrcpy( dllDeviceName[ iIndex ], mDevIfDetail -> DevicePath );  // 设备名称
	dllHandle[ iIndex ] = CreateFile( mDevIfDetail -> DevicePath, GENERIC_READ | GENERIC_WRITE,  // 打开设备,不支持重叠操作
										FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );  // 共享
	SetupDiDestroyDeviceInfoList( mDevInfo );
	return( dllHandle[ iIndex ] );
}

VOID	WINAPI	CH375CloseDevice(  // 关闭CH375设备
	ULONG			iIndex )  // 指定CH375设备序号
{
	dllIntRoutine[ iIndex ] = NULL;  // 取消中断服务程序
	if ( dllIntThreadId[ iIndex ] ) CH375SetIntRoutine( iIndex, NULL );  // 等待线程结束
//	CH375AbortRead( iIndex );  // 放弃数据块读操作
//	CH375AbortWrite( iIndex );  // 放弃数据块写操作
	CloseHandle( dllHandle[ iIndex ] );  // 关闭句柄
	dllHandle[ iIndex ] = INVALID_HANDLE_VALUE;
}

ULONG	WINAPI	CH375GetVersion( )  // 获得DLL版本号,返回版本号
{
	return( mTHIS_VERSION );
}

ULONG	WINAPI	CH375DriverCommand(  // 直接传递命令给驱动程序,出错则返回0,否则返回数据长度
	ULONG			iIndex,  // 指定CH375设备序号
	mPWIN32_COMMAND	ioCommand )  // 命令结构的指针
// 该程序在调用后返回数据长度,并且仍然返回命令结构,如果是读操作,则数据返回在命令结构中,
// 返回的数据长度在操作失败时为0,操作成功时为整个命令结构的长度,例如读一个字节,则返回mWIN32_COMMAND_HEAD+1,
// 命令结构在调用前,分别提供:管道号或者命令功能代码,存取数据的长度(可选),数据(可选)
// 命令结构在调用后,分别返回:操作状态代码,后续数据的长度(可选),
//   操作状态代码是由WINDOWS定义的代码,可以参考NTSTATUS.H,
//   后续数据的长度是指读操作返回的数据长度,数据存放在随后的缓冲区中,对于写操作一般为0
{
	ULONG	mLength;
	mLength = ioCommand -> mLength + mWIN32_COMMAND_HEAD;  // 数据缓冲区长度加上命令结构头的长度
	if ( DeviceIoControl( dllHandle[ iIndex ], IOCTL_CH375_COMMAND, ioCommand, mLength, ioCommand, mLength, &mLength, NULL ) )
		return( mLength );  // 返回数据长度
	else return( 0 );  // 出错
}

ULONG	WINAPI	CH375GetDrvVersion( )  // 获得驱动程序版本号,返回版本号,出错则返回0
{
	ULONG			mIndex;
	ULONG			mLength;
	mWIN32_COMMAND	mCommand;
	mLength = sizeof( mWIN32_COMMAND );
	for ( mIndex = 0; mIndex < mCH375_MAX_NUMBER; ++mIndex ) if ( dllHandle[ mIndex ] != INVALID_HANDLE_VALUE ) break;  // 搜索一个有效句柄
	if ( mIndex < mCH375_MAX_NUMBER ) {  // 设备句柄有效
		mCommand.mFunction = mFuncGetVersion;
		mCommand.mLength = 0;
		if ( DeviceIoControl( dllHandle[ mIndex ], IOCTL_CH375_COMMAND, &mCommand, mLength, &mCommand, mLength, &mLength, NULL ) )
			return( mCommand.mBuffer[0] );  // 正常返回驱动程序的版本号
		else return( 0 );  // 出错
	}
	else return( 0 );  // 没有有效的设备句柄,出错
}

BOOL	WINAPI	CH375ResetDevice(  // 复位USB设备
	ULONG			iIndex )  // 指定CH375设备序号
{
	ULONG			mLength;
	mWIN32_COMMAND	mCommand;
	mCommand.mFunction = mFuncResetDevice;  // 复位设备
	mCommand.mLength = 0;
	mLength = sizeof( mWIN32_COMMAND );  // 缓冲区长度,默认命令结构的长度
	if ( DeviceIoControl( dllHandle[ iIndex ], IOCTL_CH375_COMMAND, &mCommand, mLength, &mCommand, mLength, &mLength, NULL ) )
		return( TRUE );
	else return( FALSE );  // 出错
}

BOOL	WINAPI	CH375GetDeviceDescr(  // 读取设备描述符
	ULONG			iIndex,  // 指定CH375设备序号
	PVOID			oBuffer,  // 指向一个足够大的缓冲区,用于保存描述符
	PULONG			ioLength )  // 指向长度单元,输入时为准备读取的长度,返回后为实际读取的长度
{
	UCHAR			mBuffer[ mDEFAULT_COMMAND_LEN ];
	ULONG			mLength;
	mPWIN32_COMMAND	mpCommand;
	if ( *ioLength > mDEFAULT_BUFFER_LEN ) *ioLength = mDEFAULT_BUFFER_LEN;  // 限制长度
	mpCommand = (PVOID)mBuffer;
	mpCommand -> mFunction = mPipeDeviceCtrl;  // 通过综合控制管道获取USB设备描述符
	mpCommand -> mLength = sizeof( mUSB_SETUP_PKT );  // 数据长度,指写入综合控制管道的命令请求包的长度
	mpCommand -> mSetupPkt.mUspReqType = 0x80;  // 请求类型
	mpCommand -> mSetupPkt.mUspRequest = mUSB_GET_DESCR;  // 请求码 USB_REQUEST_GET_DESCRIPTOR
	mpCommand -> mSetupPkt.mUspValueLow = 0x00;  // 描述符索引
	mpCommand -> mSetupPkt.mUspValueHigh = 0x01;  // 设备描述符 USB_DEVICE_DESCRIPTOR_TYPE
	mpCommand -> mSetupPkt.mUspIndex = 0x0000;  // 索引参数
	mpCommand -> mSetupPkt.mLength = (USHORT)*ioLength;  // 需要读取的数据长度
	mLength = *ioLength + mWIN32_COMMAND_HEAD;  // 缓冲区长度,数据长度加上命令结构头的长度
	if ( DeviceIoControl( dllHandle[ iIndex ], IOCTL_CH375_COMMAND, mpCommand, sizeof( mWIN32_COMMAND ), mpCommand, mLength, &mLength, NULL ) ) {
		*ioLength = mpCommand -> mLength;  //  返回实际读取数据的长度
		CopyMemory( oBuffer, & mpCommand -> mBuffer[0], *ioLength );  // 返回读取的数据
		return( TRUE );
	}
	else {  // 出错
		*ioLength = 0;
		return( FALSE );
	}
}

BOOL	WINAPI	CH375GetConfigDescr(  // 读取配置描述符
	ULONG			iIndex,  // 指定CH375设备序号
	PVOID			oBuffer,  // 指向一个足够大的缓冲区,用于保存描述符
	PULONG			ioLength )  // 指向长度单元,输入时为准备读取的长度,返回后为实际读取的长度
{
	UCHAR			mBuffer[ mDEFAULT_COMMAND_LEN ];
	ULONG			mLength;
	mPWIN32_COMMAND	mpCommand;
	if ( *ioLength > mDEFAULT_BUFFER_LEN ) *ioLength = mDEFAULT_BUFFER_LEN;  // 限制长度
	mpCommand = (PVOID)mBuffer;
	mpCommand -> mFunction = mFuncGetConfig;  // 获取USB配置描述符
	mpCommand -> mLength = *ioLength;  // 数据长度

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -