?? ch375dll.c
字號:
// 這是CH372和CH375的Windows98/ME/2000/XP簡化版驅動程序, 僅供學習USB驅動開發
// 稍加修改完全可以用于其它USB芯片, 不過作者希望你是用于CH372和CH375芯片
// 2003.09.08, 2003.12.28, 2004.10.15, 2004.12.05, 2004.12.10, 2005.01.20, 2005.02.23, 2005.07.15
//****************************************
//** Copyright (C) W.ch 1999-2005 **
//** Web: http://www.winchiphead.com **
//****************************************
//** DLL for USB interface chip CH375 **
//** C, VC5.0 **
//****************************************
//
// USB總線接口芯片CH375的應用層接口庫 V0.1
// 南京沁恒電子有限公司 作者: W.ch 2005.07
// CH375-DLL V0.1 , 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 <dbt.h>
#include "CH375DLL.H"
BOOL WINAPI DLLMain( // 動態鏈接庫的入口
HINSTANCE iInstance,
ULONG iReason,
LPVOID iReserved );
ULONG WINAPI dllInterruptThread( // 中斷模擬線程
LPVOID iParameter );
#define mTHIS_VERSION 0x01 // 當前版本
static const GUID CH375Guid = { 0x5e7f6bdf, 0x1ce5, 0x4d78, { 0xbb, 0xcf, 0xd2, 0xc, 0x44, 0x32, 0x9f, 0x7d } }; // GUID
HANDLE dllHandle; // CH375設備句柄
mPCH375_INT_ROUTINE dllIntRoutine; // CH375中斷服務回調程序
ULONG dllIntThreadId; // CH375中斷模擬線程的標識符
UCHAR dllDeviceName[128]; // CH375設備名字符串
BOOL WINAPI DLLMain( // 動態鏈接庫的入口
HINSTANCE iInstance,
ULONG iReason,
LPVOID iReserved )
{
return( TRUE );
}
ULONG WINAPI dllInterruptThread( // 中斷模擬線程,每個需要中斷功能的CH375設備都具有一個線程
LPVOID iParameter )
{
HANDLE dllHandleOverlap; // CH375設備句柄,可以執行重疊操作
HANDLE mEvent;
BOOL mResult;
ULONG mLength;
mWIN32_COMMAND mCommand;
OVERLAPPED mOverlapped;
mPCH375_INT_ROUTINE mIntRoutine;
dllHandleOverlap = CreateFile( (PUCHAR)iParameter, GENERIC_READ | GENERIC_WRITE, // 打開設備,支持重疊操作
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL );
if ( dllHandleOverlap != INVALID_HANDLE_VALUE ) { // 打開設備成功
mEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); // 初始化完成事件
while ( dllIntRoutine ) { // 等待中斷直到取消
mCommand.mFunction = mPipeInterUp; // 從中斷數據上傳管道讀取數據
mCommand.mLength = mCH375_PKT_LEN_SHORT; // 數據長度
mLength = sizeof( mWIN32_COMMAND ); // 緩沖區長度,數據長度加上命令結構頭的長度
mOverlapped.Internal = 0;
mOverlapped.InternalHigh = 0;
mOverlapped.Offset = 0;
mOverlapped.OffsetHigh = 0;
mOverlapped.hEvent = mEvent;
ResetEvent( mEvent ); // 初始化完成事件
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 ) { // 發生中斷事件則調用中斷服務回調程序
if ( mIntRoutine = dllIntRoutine ) mIntRoutine( & mCommand.mBuffer[0] ); // 發生中斷事件則調用中斷服務回調程序,將當前的中斷特征數據提供給中斷服務程序
}
if ( mResult == FALSE && dllIntRoutine ) Sleep( 5 ); // 出錯則延時5毫秒
}
CloseHandle( mEvent );
CloseHandle( dllHandleOverlap ); // 關閉句柄
}
dllIntThreadId = 0;
ExitThread( 0 ); // 退出
return( 0 );
}
ULONG WINAPI CH375GetVersion( ) // 獲得DLL版本號,返回版本號
{
return( mTHIS_VERSION );
}
PVOID WINAPI CH375GetDeviceName( // 返回指向CH375設備名稱的緩沖區,出錯則返回NULL
ULONG iIndex ) // 指定CH375設備序號,0對應第一個設備
{
UCHAR mBuffer[1024];
LPGUID mClassGuid;
HDEVINFO mDevInfo;
SP_INTERFACE_DEVICE_DATA mDevIfData;
PSP_INTERFACE_DEVICE_DETAIL_DATA mDevIfDetail;
mClassGuid = ( LPGUID )&CH375Guid; // 設備類
mDevInfo = SetupDiGetClassDevs( mClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE ); // 獲得指定設備類
if ( mDevInfo == INVALID_HANDLE_VALUE ) return( NULL );
mDevIfData.cbSize = sizeof( mDevIfData );
if ( !SetupDiEnumDeviceInterfaces( mDevInfo, NULL, mClassGuid, iIndex, &mDevIfData ) ) { // 枚舉指定序號的設備
SetupDiDestroyDeviceInfoList( mDevInfo );
return( NULL );
}
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( NULL );
}
lstrcpy( dllDeviceName, mDevIfDetail -> DevicePath ); // 設備名稱
SetupDiDestroyDeviceInfoList( mDevInfo );
return( dllDeviceName );
}
HANDLE WINAPI CH375OpenDevice( // 打開CH375設備,返回句柄,出錯則無效
ULONG iIndex ) // 指定CH375設備序號,0對應第一個設備
{
dllHandle = CreateFile( CH375GetDeviceName( iIndex ), GENERIC_READ | GENERIC_WRITE, // 打開設備,不支持重疊操作
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); // 共享
return( dllHandle );
}
VOID WINAPI CH375CloseDevice( // 關閉CH375設備
ULONG iIndex ) // 指定CH375設備序號,必須是0
{
dllIntRoutine = NULL; // 取消中斷服務程序
if ( dllIntThreadId ) CH375SetIntRoutine( 0, NULL ); // 等待線程結束
CloseHandle( dllHandle ); // 關閉句柄
}
ULONG WINAPI CH375DriverCommand( // 直接傳遞命令給驅動程序,出錯則返回0,否則返回數據長度
ULONG iIndex, // 指定CH375設備序號,必須是0
mPWIN32_COMMAND ioCommand ) // 命令結構的指針
// 該程序在調用后返回數據長度,并且仍然返回命令結構,如果是讀操作,則數據返回在命令結構中,
// 返回的數據長度在操作失敗時為0,操作成功時為整個命令結構的長度,例如讀一個字節,則返回mWIN32_COMMAND_HEAD+1,
// 命令結構在調用前,分別提供:管道號或者命令功能代碼,存取數據的長度(可選),數據(可選)
// 命令結構在調用后,分別返回:操作狀態代碼,后續數據的長度(可選),
// 操作狀態代碼是由WINDOWS定義的代碼,可以參考NTSTATUS.H,
// 后續數據的長度是指讀操作返回的數據長度,數據存放在隨后的緩沖區中,對于寫操作一般為0
{
ULONG mLength;
mLength = ioCommand -> mLength + mWIN32_COMMAND_HEAD; // 數據緩沖區長度加上命令結構頭的長度
if ( DeviceIoControl( dllHandle, IOCTL_CH375_COMMAND, ioCommand, mLength, ioCommand, mLength, &mLength, NULL ) )
return( mLength ); // 返回數據長度
else return( 0 ); // 出錯
}
BOOL WINAPI CH375GetDeviceDescr( // 讀取設備描述符
ULONG iIndex, // 指定CH375設備序號,必須是0
PVOID oBuffer, // 指向一個足夠大的緩沖區,用于保存描述符
PULONG ioLength ) // 指向長度單元,輸入時為準備讀取的長度,返回后為實際讀取的長度
{
UCHAR mBuffer[ mMAX_COMMAND_LENGTH ];
ULONG mLength;
mPWIN32_COMMAND mpCommand;
if ( *ioLength > mMAX_BUFFER_LENGTH ) *ioLength = mMAX_BUFFER_LENGTH; // 限制長度
mpCommand = (PVOID)mBuffer;
mpCommand -> mFunction = mPipeDeviceCtrl; // 通過綜合控制管道獲取USB設備描述符
mpCommand -> mLength = sizeof( mUSB_SETUP_PKT ); // 數據長度,指寫入綜合控制管道的命令請求包的長度
mpCommand -> mSetupPkt.mUspReqType = 0x80; // 請求類型
mpCommand -> mSetupPkt.mUspRequest = 0x06; // 請求碼 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, 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設備序號,必須是0
PVOID oBuffer, // 指向一個足夠大的緩沖區,用于保存描述符
PULONG ioLength ) // 指向長度單元,輸入時為準備讀取的長度,返回后為實際讀取的長度
{
UCHAR mBuffer[ mMAX_COMMAND_LENGTH ];
ULONG mLength;
mPWIN32_COMMAND mpCommand;
if ( *ioLength > mMAX_BUFFER_LENGTH ) *ioLength = mMAX_BUFFER_LENGTH; // 限制長度
mpCommand = (PVOID)mBuffer;
mpCommand -> mFunction = mPipeDeviceCtrl; // 通過綜合控制管道獲取USB設備描述符
mpCommand -> mLength = sizeof( mUSB_SETUP_PKT ); // 數據長度,指寫入綜合控制管道的命令請求包的長度
mpCommand -> mSetupPkt.mUspReqType = 0x80; // 請求類型
mpCommand -> mSetupPkt.mUspRequest = 0x06; // 請求碼 USB_REQUEST_GET_DESCRIPTOR
mpCommand -> mSetupPkt.mUspValueLow = 0x00; // 描述符索引
mpCommand -> mSetupPkt.mUspValueHigh = 0x02; // 設備描述符 USB_CONFIG_DESCRIPTOR_TYPE
mpCommand -> mSetupPkt.mUspIndex = 0x0000; // 索引參數
mpCommand -> mSetupPkt.mLength = (USHORT)*ioLength; // 需要讀取的數據長度
mLength = *ioLength + mWIN32_COMMAND_HEAD; // 緩沖區長度,數據長度加上命令結構頭的長度
if ( DeviceIoControl( dllHandle, 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;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -