📄 usbhid.cpp
字号:
/******************************************************************************************
FileName : USBHid.cpp
Author : Dekimo - Mike Vogeleer
Date Of Creation: 22/09/2003
Purpose : HID device communication
---------------------------------------
Change History :
---------------------------------------
******************************************************************************************/
#include "stdafx.h"
#include "USBHid.h"
// ----------------------------------------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------------------------------------
// Support for different DDK versions.
// ----------------------------------------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------------------------------------
// Define one of these macros below to select the DDK version:
#define DDK_2000_DDK // Retired Windows 2000 DDK
//#define DDK_XP_SP1_DDK // Latest Windows XP SP1, Windows XP, Windows 2000, Windows Millenium Edition.
//#define DDK_SERVER_2003_DDK // Latest Windows Server 2003, Windows XP SP1, Windows XP, Windows 2000.
// There are many versions of these files dangling around
// in the Visual Studio, the SDK and various DDK directories.
// All the pathnames will be completely spelled out (instead
// of using compiler/linker setting), to avoid ambiguity.
#ifdef DDK_2000_DDK
#pragma message ("Using retired Windows 2000 DDK")
// Use the setupapi.lib that comes with the compiler
// (even though the DDK also has a setupapi.lib library)
#pragma comment (lib, "setupapi.lib")
// Use the hid.lib file from the appropriate DDK directory
#pragma comment (lib, "\\winddk\\2600\\lib\\w2k\\i386\\hid.lib")
#endif
#ifdef DDK_XP_SP1_DDK
#pragma message ("Using Windows XP SP1 DDK")
// Use the setupapi.lib file that comes with the compiler
// (even though the DDK also has a setupapi.lib library)
#pragma comment (lib, "setupapi.lib")
// Use the hid.lib file from the appropriate DDK directory
#pragma comment (lib, "\\winddk\\2600\\lib\\wxp\\i386\\hid.lib")
//#pragma comment (lib, "\\winddk\\2600\\lib\\wxp\\i386\\hid.lib")
#endif
#ifdef DDK_SERVER_2003_DDK
#pragma message ("Using Windows Server 2003 DDK")
// Use the setupapi.lib file that comes with the compiler
// (even though the DDK also has a setupapi.lib library)
#pragma comment (lib, "setupapi.lib")
// Use the hid.lib file from the appropriate DDK directory
#pragma comment (lib, "\\winddk\\3790\\lib\\w2k\\i386\\hid.lib")
//#pragma comment (lib, "\\winddk\\3790\\lib\\wxp\\i386\\hid.lib")
#endif
// ----------------------------------------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------------------------------------
#define PKT_SIZE (8)
static HANDLE hUSBRead; // Handle to read from USB device
static HANDLE hUSBWrite; // Handle to write to USB device
static USB_CALLBACK_FUNCTION USB_callback_function; // Callback function when data arrives
static const void* extraInfo; // Parameter for callback function (in practice: HWND or CDialog*)
static BYTE buf[1 + PKT_SIZE]; // Receive buffer
static HANDLE hThread=0; // Read thread
static HANDLE hDevNotify=0; // For WindowProc() notifications of USB connect/disconnect.
// Forward declarations of helper functions:
static int hid_open(const CWnd* pNotifyWnd,HANDLE* hDevNotify,
HANDLE* DeviceHandleRead,HANDLE* DeviceHandleWrite,
unsigned VendorID,unsigned ProductID,unsigned* versionnr=0,
unsigned* usage=0,unsigned *usagepage=0,
unsigned* inputreportlength=0,unsigned* outputreportlength=0,
unsigned* featurereportlength=0);
static int UsbHidStep(void);
static OVERLAPPED overlapped; // Must do overlapped IO (if we don't, a blocking ReadFile in one thread will cause a deadlock on CloseHandle() in the other thread)
static HANDLE hEventObject;
static volatile BYTE ThreadMayContinue;
static HANDLE hThreadDone;
static DWORD WINAPI InterruptThreadProc(LPVOID lpParameter) {
// Setup the EventObject and the overlapped structure for overlapped, asynchronous IO.
hEventObject = CreateEvent(NULL,0,0,"");
hThreadDone = CreateEvent(NULL,0,0,"");
overlapped.hEvent = hEventObject;
overlapped.Offset = 0;
overlapped.OffsetHigh = 0;
// Maintain bookkeeping info to handle thread termination
ThreadMayContinue=1;
while(ThreadMayContinue) {
if(UsbHidStep())
break;
}
::CloseHandle(hEventObject);
if(hThreadDone) SetEvent(hThreadDone);
return 1;
}
static int UsbHidStep(void) { // Drives RX state machine
DWORD ulBytesSucceed=0,ulBytesRequest=PKT_SIZE/*+4*/;
// Non-blocking, asynchronous, overlapped ReadFile(). This function returns immediately
ReadFile(hUSBRead,(unsigned char*)buf, ulBytesRequest=PKT_SIZE+1/*+4*/, &ulBytesSucceed, &overlapped);
// If data arrives, hEventObject will be signalled and the data will be in buf[].
// If data does not arrive, WaitForSingleObject() returns after 100ms. This allows to
// terminate the thread when ThreadMayContinue becomes false.
switch (WaitForSingleObject(hEventObject,100)) {
case WAIT_OBJECT_0: { // Data arrived
if(!GetOverlappedResult(hUSBRead,&overlapped,&ulBytesSucceed,0)) { // Get number of received bytes
USB_callback_function(0,extraInfo);
break; // Device was disconnected!
}
if(ulBytesSucceed==ulBytesRequest) {
if(ThreadMayContinue)
USB_callback_function(buf,extraInfo);
} else {
return 1;
}
break;
}
case WAIT_TIMEOUT: { // If nothing arrived during those 100msec, cancel our IO request
CancelIo(hUSBRead);
break;
default:
break;
}
}
return 0;
}
unsigned char UsbHidOpen(USB_CALLBACK_FUNCTION usb_callback_function,const CWnd* p) {
unsigned version,usage,usagepage,ilen,olen;
if(hid_open(p,&hDevNotify,&hUSBRead,&hUSBWrite,0x10C4,0x0001,&version,&usage,&usagepage,&ilen,&olen)) {
DWORD id;
USB_callback_function=usb_callback_function;
extraInfo=(const void*)p;
hThread=0;
hThread=CreateThread(0,4096,InterruptThreadProc,0/*lpParameter*/,0,&id);
return 0;
}
return 3;
}
DWORD UsbHidWrite(BYTE* buf) { // Write to device
buf[0]=0; // First byte is report number (should be 0)
DWORD ulBytesSucceed=0,ulBytesRequest=PKT_SIZE+1;
WriteFile(hUSBWrite, buf , ulBytesRequest, &ulBytesSucceed, NULL);
if(ulBytesSucceed != ulBytesRequest) {
return 1;
}
return 0;
}
void UsbHidClose(void) {
// Notify the thread that it should finished asap.
ThreadMayContinue=0;
// Tell windows we are not interested in device notification messages any more
if(IsWin2KorXP()) {
if(hDevNotify) UnregisterDeviceNotification(hDevNotify);
hDevNotify=0;
}
if(hThread) {
if(WAIT_OBJECT_0==WaitForSingleObject(hThreadDone,100)) {
::CloseHandle(hThread); // If the thread is not finished, CloseHandle() would block indefinitely
}
::CloseHandle(hThreadDone);hThreadDone=0;
}
hThread=0;
if ( hUSBRead != NULL ) {
::CloseHandle(hUSBRead);
hUSBRead = NULL;
}
if ( hUSBWrite != NULL ) {
::CloseHandle(hUSBWrite);
hUSBWrite = NULL;
}
}
BOOL IsWin2KorXP(void) {
OSVERSIONINFO VersionInfo;
VersionInfo.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
GetVersionEx(&VersionInfo);
return (VersionInfo.dwMajorVersion==5);
}
// ------------------------------------------------------------------------------------
// ----------------------- Helper functions (very HID specific) -----------------------
// ------------------------------------------------------------------------------------
// There are many versions of these files dangling around
// in the Visual Studio, the SDK and various DDK directories.
// All the pathnames will be completely spelled out (instead
// of using compiler/linker setting), to avoid ambiguity.
#ifdef DDK_2000_DDK
#include "/winddk/2600/inc/w2k/initguid.h"
#define MAX_LOADSTRING 256
extern "C" {
//#include "/ntddk/inc/hidsdi.h"
//}
//#include "/ntddk/inc/setupapi.h"
#include "/winddk/2600/inc/w2k/hidsdi.h"
//#include "/winddk/2600/inc/ddk/wdm/w2k/hidsdi.h"
//#include "/winddk/2600/inc/wxp/hidsdi.h"
//#include "/winddk/2600/inc/ddk/wdm/wxp/hidsdi.h"
}
#include "/winddk/2600/inc/w2k/setupapi.h"
#include <dbt.h>
#endif
#ifdef DDK_XP_SP1_DDK
#include "/winddk/2600/inc/w2k/initguid.h"
#define MAX_LOADSTRING 256
extern "C" {
#include "/winddk/2600/inc/w2k/hidsdi.h"
//#include "/winddk/2600/inc/ddk/wdm/w2k/hidsdi.h"
//#include "/winddk/2600/inc/wxp/hidsdi.h"
//#include "/winddk/2600/inc/ddk/wdm/wxp/hidsdi.h"
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -