📄 ch375dll.c
字号:
// 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 + -