混合DotNet与Win32API来实现的Hidlibrary,c/c++可直接使用,c#可直接使用
异步IO,拔插事件订阅,数据读取事件订阅
工程目录结构
HidEvent.h
1 #pragma once 2 3 typedef void (*HidEvent)(); 4 typedef void (__cdecl *HidReadDataEvent)(unsigned char *data, int len);
Hidimpl.h
1 #pragma once 2 #include "HidEvent.h" 3 4 class Hidimpl 5 { 6 public: 7 Hidimpl(int vid, int pid); 8 ~Hidimpl(void); 9 10 bool FindMyDevice(); 11 void NotifyEvents(HidEvent arrival, HidEvent removed, HidReadDataEvent rdata); 12 13 int getInputLen() 14 { 15 return mInputLen; 16 } 17 18 int getOutputLen() 19 { 20 return mOutputLen; 21 } 22 23 bool IsConnected() 24 { 25 return mIsConnected; 26 } 27 28 public: 29 // IO Functions 30 //int Read(unsigned char *data, int len); 31 void Write(unsigned char *data, int len); 32 33 public: 34 static Hidimpl *mTarget; 35 static DWORD ThreadMessageRoutine(LPVOID lparam); 36 static LRESULT CALLBACK ZSHidWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); 37 38 public: 39 HidEvent mArrivalEvent; 40 HidEvent mRemovedEvent; 41 HidReadDataEvent mReadDataEvent; 42 43 private: 44 void MyDeviceRemoved(); 45 46 private: 47 int mInputLen; 48 int mOutputLen; 49 bool mIsConnected; 50 51 int mVid; 52 int mPid; 53 HANDLE mhHidRx; 54 HANDLE mhHidTx; 55 56 DWORD mThreadId; 57 HANDLE mThreadHandle; 58 59 // Managed objects FileStream 60 void *mFsRx; 61 void *mFsTx; 62 };
Hidimpl.cpp
1 #include "StdAfx.h" 2 #include "Hidimpl.h" 3 #include "HidState.h" 4 #include <vcclr.h> 5 6 #pragma comment(lib, "hid.lib") 7 #pragma comment(lib, "setupapi.lib") 8 9 using namespace System; 10 using namespace System::IO; 11 using namespace Microsoft::Win32::SafeHandles; 12 13 Hidimpl *Hidimpl::mTarget = nullptr; 14 15 Hidimpl::Hidimpl(int vid, int pid) 16 :mFsRx(nullptr), mFsTx(nullptr), 17 mArrivalEvent(nullptr), mRemovedEvent(nullptr), 18 mThreadId(0), mThreadHandle(INVALID_HANDLE_VALUE) 19 { 20 mVid = vid; 21 mPid = pid; 22 23 FindMyDevice(); 24 } 25 26 Hidimpl::~Hidimpl(void) 27 { 28 MyDeviceRemoved(); 29 if (mThreadHandle != INVALID_HANDLE_VALUE) 30 { 31 PostThreadMessage(mThreadId, WM_CLOSE, 0, 0); 32 mThreadHandle = INVALID_HANDLE_VALUE; 33 } 34 } 35 36 void Hidimpl::MyDeviceRemoved() 37 { 38 if (mFsRx) 39 { 40 gcroot<FileStream ^> *_pfs = static_cast<gcroot<FileStream ^> *>(mFsRx); 41 // not need only delete ok 42 //((FileStream ^)*_pfs)->Close(); 43 delete _pfs; 44 mFsRx = nullptr; 45 } 46 47 if (mFsTx) 48 { 49 gcroot<FileStream ^> *_pfs = static_cast<gcroot<FileStream ^> *>(mFsTx); 50 // not need only delete ok 51 //((FileStream ^)*_pfs)->Close(); 52 delete _pfs; 53 mFsTx = nullptr; 54 } 55 56 // 不需要手动关闭GC自动处理 57 // this is also a crazy fucking shit 58 // 关闭的句柄被重复关闭会引发[0xC0000008: An invalid handle was specified] 59 //CloseHandle(mhHidRx); 60 //mhHidRx = INVALID_HANDLE_VALUE; 61 //CloseHandle(mhHidTx); 62 //mhHidTx = INVALID_HANDLE_VALUE; 63 } 64 65 bool Hidimpl::FindMyDevice() 66 { 67 bool isFind = false; 68 GUID guid; 69 HidD_GetHidGuid(&guid); 70 HDEVINFO hdevinfo = SetupDiGetClassDevs(&guid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); 71 SP_DEVICE_INTERFACE_DATA device_interface_data; 72 ZeroMemory(&device_interface_data, sizeof(device_interface_data)); 73 device_interface_data.cbSize = sizeof(device_interface_data); 74 75 int device_interface_index = 0; 76 while (SetupDiEnumDeviceInterfaces(hdevinfo, NULL, &guid, device_interface_index, &device_interface_data)) 77 { 78 DWORD requireSize; 79 SetupDiGetDeviceInterfaceDetail(hdevinfo, &device_interface_data, NULL, 0, &requireSize, NULL); 80 PSP_DEVICE_INTERFACE_DETAIL_DATA psp_device_interface_detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(requireSize); 81 psp_device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); 82 if (SetupDiGetDeviceInterfaceDetail(hdevinfo, &device_interface_data, psp_device_interface_detail_data, requireSize, &requireSize, NULL)) 83 { 84 TCHAR *device_path = psp_device_interface_detail_data->DevicePath; 85 86 // 打印设备路径[将TCHAR *转换为System::String^] 87 //String ^str_path = gcnew String(device_path); 88 //Console::ForegroundColor = ConsoleColor::Blue; 89 //Console::WriteLine(str_path); 90 //Console::ResetColor(); 91 92 HANDLE handle = CreateFile(device_path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL); 93 if (handle != INVALID_HANDLE_VALUE) 94 { 95 HIDD_ATTRIBUTES hidd_attributes; 96 HidD_GetAttributes(handle, &hidd_attributes); 97 if (hidd_attributes.VendorID == mVid && hidd_attributes.ProductID == mPid) 98 { 99 PHIDP_PREPARSED_DATA phidp_preparsed_data; 100 HidD_GetPreparsedData(handle, &phidp_preparsed_data); 101 HIDP_CAPS hidp_caps; 102 HidP_GetCaps(phidp_preparsed_data, &hidp_caps); 103 mInputLen = hidp_caps.InputReportByteLength; 104 mOutputLen = hidp_caps.OutputReportByteLength; 105 HidD_FreePreparsedData(phidp_preparsed_data); 106 107 // 打印设备路径[将TCHAR *转换为System::String^] 108 String ^str_path = gcnew String(device_path); 109 Console::ForegroundColor = ConsoleColor::Green; 110 Console::WriteLine(str_path); 111 Console::ResetColor(); 112 113 mhHidRx = CreateFile(device_path, GENERIC_READ, 114 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); 115 mhHidTx = CreateFile(device_path, GENERIC_WRITE, 116 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); 117 118 SafeFileHandle ^_hRx = gcnew SafeFileHandle((IntPtr)mhHidRx, true); 119 FileStream ^_fsRx = gcnew FileStream(_hRx, FileAccess::Read, mInputLen, true); 120 // managed type conversion into unmanaged pointer is not allowed. 121 // we can use gcroot<> wrapper 122 gcroot<FileStream^> *_pfs = new gcroot<FileStream ^>(_fsRx); 123 mFsRx = static_cast<void *>(_pfs); 124 125 SafeFileHandle ^_hTx = gcnew SafeFileHandle((IntPtr)mhHidTx, true); 126 FileStream ^_fsTx = gcnew FileStream(_hTx, FileAccess::Write, mOutputLen, true); 127 // managed type conversion into unmanaged pointer is not allowed. 128 // we can use gcroot<> wrapper 129 _pfs = new gcroot<FileStream^>(_fsTx); 130 mFsTx = static_cast<void *>(_pfs); 131 132 HidState ^state = gcnew HidState(this, _fsRx, mInputLen); 133 _fsRx->BeginRead(state->mBuffer, 0, state->mBuffer->Length, gcnew AsyncCallback(state, &HidState::EndRead), state); 134 135 isFind = true; 136 CloseHandle(handle); 137 free(psp_device_interface_detail_data); 138 break; 139 } 140 141 CloseHandle(handle); 142 } 143 } 144 else 145 { 146 int error = GetLastError(); 147 Console::ForegroundColor = ConsoleColor::Blue; 148 Console::WriteLine("[SetupDiGetDeviceInterfaceDetail Error]GetLastError = " + error); 149 Console::ResetColor(); 150 } 151 152 device_interface_index++; 153 free(psp_device_interface_detail_data); 154 } 155 156 SetupDiDestroyDeviceInfoList(hdevinfo); 157 mIsConnected = isFind; 158 159 return isFind; 160 } 161 162 void Hidimpl::NotifyEvents(HidEvent arrival, HidEvent removed, HidReadDataEvent rdata) 163 { 164 // Cannt reset event to device 165 if (mThreadHandle != INVALID_HANDLE_VALUE) return; 166 167 mArrivalEvent = arrival; 168 mRemovedEvent = removed; 169 mReadDataEvent = rdata; 170 171 mThreadHandle = CreateThread(NULL, 0, 172 (LPTHREAD_START_ROUTINE)ThreadMessageRoutine, this, THREAD_PRIORITY_NORMAL, &mThreadId); 173 } 174 175 DWORD Hidimpl::ThreadMessageRoutine(LPVOID lparam) 176 { 177 mTarget = static_cast<Hidimpl *>(lparam); 178 HINSTANCE hInstance = reinterpret_cast<HINSTANCE>(GetModuleHandle(NULL)); 179 180 WNDCLASS wndClass = {0}; 181 wndClass.lpfnWndProc = ZSHidWndProc; 182 wndClass.lpszClassName = L"ZSHidlib"; 183 wndClass.hInstance = hInstance; 184 if (RegisterClass(&wndClass)) 185 { 186 // 为线程消息循环(HWND_MESSAGE) 187 HWND hwnd = CreateWindowEx(0, wndClass.lpszClassName, NULL, 188 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, hInstance, NULL); 189 if (hwnd != INVALID_HANDLE_VALUE) 190 { 191 GUID guid; 192 HidD_GetHidGuid(&guid); 193 DEV_BROADCAST_DEVICEINTERFACE notifycationFilter = {0}; 194 notifycationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); 195 notifycationFilter.dbcc_classguid = guid; 196 notifycationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; 197 HDEVNOTIFY hdevnotify = RegisterDeviceNotification(hwnd, ¬ifycationFilter, DEVICE_NOTIFY_WINDOW_HANDLE); 198 199 if (hdevnotify != INVALID_HANDLE_VALUE) 200 { 201 Console::ForegroundColor = ConsoleColor::Blue; 202 Console::WriteLine("Notify注册成功,即将进入消息循环."); 203 Console::ResetColor(); 204 205 MSG msg; 206 if (GetMessage(&msg, NULL, 0, 0) > 0) 207 { 208 TranslateMessage(&msg); 209 DispatchMessage(&msg); 210 } 211 } 212 213 Console::ForegroundColor = ConsoleColor::Blue; 214 Console::WriteLine("退出消息循环........................"); 215 Console::ResetColor(); 216 217 UnregisterDeviceNotification(hdevnotify); 218 DestroyWindow(hwnd); 219 UnregisterClass(wndClass.lpszClassName, hInstance); 220 } 221 } 222 223 return 0; 224 } 225 226 LRESULT CALLBACK Hidimpl::ZSHidWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 227 { 228 if (msg == WM_DEVICECHANGE) 229 { 230 switch (wparam) 231 { 232 case DBT_DEVICEARRIVAL: 233 { 234 if (!mTarget->mIsConnected) 235 { 236 if (mTarget->FindMyDevice()) 237 { 238 Console::ForegroundColor = ConsoleColor::Blue; 239 Console::WriteLine("MY HID DEVICE IS FOUND AND OPEN."); 240 Console::ResetColor(); 241 242 // My device arrival event 243 if (mTarget->mArrivalEvent != nullptr) 244 mTarget->mArrivalEvent(); 245 } 246 } 247 } 248 break; 249 case DBT_DEVICEREMOVECOMPLETE: 250 { 251 if (mTarget->mIsConnected) 252 { 253 if (!mTarget->FindMyDevice()) 254 { 255 Console::ForegroundColor = ConsoleColor::Blue; 256 Console::WriteLine("MY HID DEVICE REMOVED."); 257 Console::ResetColor(); 258 259 // My device remove event 260 mTarget->MyDeviceRemoved(); 261 if (mTarget->mRemovedEvent != nullptr) 262 mTarget->mRemovedEvent(); 263 } 264 } 265 } 266 break; 267 default: 268 break; 269 } 270 } 271 272 return DefWindowProc(hwnd, msg, wparam, lparam); 273 } 274 275 void Hidimpl::Write(unsigned char *data, int len) 276 { 277 if (!mIsConnected) return; 278 array<unsigned char> ^_data = gcnew array<unsigned char>(mOutputLen); 279 try 280 { 281 int length = len>mOutputLen?mOutputLen:len; 282 for (int i = 0; i < length; i++) _data[i] = data[i]; 283 284 if (mFsTx != nullptr) 285 { 286 gcroot<FileStream^> *_pfs = static_cast<gcroot<FileStream^> *>(mFsTx); 287 //((FileStream^)*_pfs)->Write(_data, 0, _data->Length); 288 ((FileStream^)*_pfs)->BeginWrite(_data, 0, _data->Length, nullptr, nullptr); 289 ((FileStream^)*_pfs)->Flush(); 290 } 291 } 292 catch(IOException ^e) 293 { 294 Console::WriteLine(e->Message); 295 } 296 catch(Exception ^e) 297 { 298 Console::WriteLine(e->Message); 299 } 300 }
HidState.h
1 #pragma once 2 #include "Hidimpl.h" 3 4 using namespace System; 5 using namespace System::IO; 6 7 public ref class HidState 8 { 9 public: 10 HidState(Hidimpl *hid, FileStream ^fs, int bufferLen); 11 ~HidState(); 12 void EndRead(IAsyncResult ^ar); 13 14 public: 15 Hidimpl *mHidimpl; 16 FileStream ^mFileStream; 17 array<unsigned char> ^mBuffer; 18 };
HidState.cpp
1 #include "stdafx.h" 2 #include "HidState.h" 3 4 HidState::HidState(Hidimpl *hid, FileStream ^fs, int bufferLen) 5 { 6 mHidimpl = hid; 7 mFileStream = fs; 8 mBuffer = gcnew array<unsigned char>(bufferLen); 9 } 10 11 HidState::~HidState() 12 { 13 mHidimpl = nullptr; 14 } 15 16 void HidState::EndRead(IAsyncResult ^ar) 17 { 18 HidState ^state = dynamic_cast<HidState ^>(ar->AsyncState); 19 try 20 { 21 int count = state->mFileStream->EndRead(ar); 22 // [有数据读入的情况下]调用ReadData事件 23 if (mHidimpl->mReadDataEvent != nullptr && count > 0) 24 { 25 unsigned char *ptrdt = new unsigned char[count]; 26 for (int i = 0; i < count; i++) ptrdt[i] = mBuffer[i]; 27 // 此处封送到C#的IntPtr指针(this a crazy fucking) 28 mHidimpl->mReadDataEvent(ptrdt, count); 29 delete []ptrdt; 30 } 31 if (mHidimpl->IsConnected()) 32 state->mFileStream->BeginRead(state->mBuffer, 0, mBuffer->Length, gcnew AsyncCallback(this, &HidState::EndRead), state); 33 } 34 catch(IOException ^e) 35 { 36 Console::WriteLine(e->Message); 37 } 38 catch(Exception ^e) 39 { 40 Console::WriteLine(e->Message); 41 } 42 }
_______export,wrap managed clr class for csharp
Hidlib.h
1 #pragma once 2 #include "Hidimpl.h" 3 4 using namespace System; 5 6 public ref class Hidlib 7 { 8 public: 9 delegate void HidDelegate(); 10 delegate void HidReadDataDelegate(IntPtr data, int len); 11 12 public: 13 Hidlib(int vid, int pid); 14 void NotifyEvents(HidDelegate ^arrival, HidDelegate ^removed, HidReadDataDelegate ^rdata); 15 void Write(array<unsigned char> ^data); 16 17 private: 18 Hidimpl *impl; 19 };
Hidlib.cpp
1 #include "stdafx.h" 2 #include "Hidlib.h" 3 #include <vcclr.h> 4 5 using namespace System::IO; 6 using namespace System::Runtime::InteropServices; 7 8 Hidlib::Hidlib(int vid, int pid) 9 { 10 impl = new Hidimpl(vid, pid); 11 } 12 13 void Hidlib::NotifyEvents(HidDelegate ^arrival, HidDelegate ^removed, HidReadDataDelegate ^rdata) 14 { 15 IntPtr _arrival = Marshal::GetFunctionPointerForDelegate(arrival); 16 IntPtr _removed = Marshal::GetFunctionPointerForDelegate(removed); 17 IntPtr _rdata = Marshal::GetFunctionPointerForDelegate(rdata); 18 impl->NotifyEvents((HidEvent)_arrival.ToPointer(), (HidEvent)_removed.ToPointer(), (HidReadDataEvent)_rdata.ToPointer()); 19 } 20 21 void Hidlib::Write(array<unsigned char> ^data) 22 { 23 try 24 { 25 int length = data->Length>impl->getOutputLen()?impl->getOutputLen():data->Length; 26 if (impl->mFsTx != nullptr) 27 { 28 gcroot<FileStream^> *_pfs = static_cast<gcroot<FileStream^> *>(impl->mFsTx); 29 //((FileStream^)*_pfs)->Write(_data, 0, _data->Length); 30 ((FileStream^)*_pfs)->BeginWrite(data, 0, length, nullptr, nullptr); 31 ((FileStream^)*_pfs)->Flush(); 32 } 33 } 34 catch(IOException ^e) 35 { 36 Console::WriteLine(e->Message); 37 } 38 catch(Exception ^e) 39 { 40 Console::WriteLine(e->Message); 41 } 42 }
- 提供PInvoke接口
PInvoke(平台调用)
1 #pragma once 2 #include <Hidimpl.h> 3 #include "HidEvent.h" 4 5 #ifdef ZSHIDLIB_EXPORTS 6 #define ZSHIDLIB_API __declspec(dllexport) 7 #else 8 #define ZSHIDLIB_API __declspec(dllimport) 9 #endif 10 11 #ifdef __cplusplus 12 extern "C" { 13 #endif 14 ZSHIDLIB_API void Open(int vid, int pid); 15 ZSHIDLIB_API bool IsOpen(); 16 ZSHIDLIB_API bool IsConnected(); 17 ZSHIDLIB_API int getInputLen(); 18 ZSHIDLIB_API int getOutputLen(); 19 ZSHIDLIB_API void Notify(HidEvent arrival, HidEvent removed, HidReadDataEvent rdata); 20 ZSHIDLIB_API void Write(unsigned char *data, int len); 21 ZSHIDLIB_API void Close(); 22 #ifdef __cplusplus 23 }; 24 #endif
1 #include "stdafx.h" 2 #include "Hidlib.h" 3 #include "Hidimpl.h" 4 5 Hidimpl *pHidimpl = nullptr; 6 7 ZSHIDLIB_API void Open(int vid, int pid) 8 { 9 if (pHidimpl == nullptr) 10 pHidimpl = new Hidimpl(vid, pid); 11 } 12 13 ZSHIDLIB_API bool IsOpen() 14 { 15 return (pHidimpl != nullptr); 16 } 17 18 ZSHIDLIB_API bool IsConnected() 19 { 20 if (pHidimpl != nullptr) 21 return pHidimpl->IsConnected(); 22 23 return 0; 24 } 25 26 ZSHIDLIB_API int getInputLen() 27 { 28 if (pHidimpl != nullptr) 29 return pHidimpl->getInputLen(); 30 31 return 0; 32 } 33 34 ZSHIDLIB_API int getOutputLen() 35 { 36 if (pHidimpl != nullptr) 37 return pHidimpl->getOutputLen(); 38 39 return 0; 40 } 41 42 ZSHIDLIB_API void Notify(HidEvent arrival, HidEvent removed, HidReadDataEvent rdata) 43 { 44 if (pHidimpl != nullptr) 45 { 46 pHidimpl->NotifyEvents(arrival, removed, rdata); 47 } 48 } 49 50 ZSHIDLIB_API void Write(unsigned char *data, int len) 51 { 52 if (pHidimpl != nullptr) 53 pHidimpl->Write(data, len); 54 } 55 56 ZSHIDLIB_API void Close() 57 { 58 if (pHidimpl != nullptr) 59 { 60 delete pHidimpl; 61 pHidimpl = nullptr; 62 } 63 }
- C#中的使用
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Runtime.InteropServices; 6 7 namespace ZSHidApp 8 { 9 delegate void HidEvent(); 10 delegate void HidReadDataEvent(IntPtr data, int len); 11 12 class Program 13 { 14 //[DllImport("ZSHidlib.dll")] 15 //public static extern void Open(int vid, int pid); 16 17 //[DllImport("ZSHidlib.dll")] 18 //public static extern void Notify(HidEvent arrival, HidEvent removed, HidReadDataEvent rdata); 19 20 //[DllImport("ZSHidlib.dll")] 21 //public static extern void Write(Byte[] data, int len); 22 23 //[DllImport("ZSHidlib.dll")] 24 //public static extern void GetData(ref Byte[] data, int len); 25 26 static void ReadData(IntPtr data, int len) 27 { 28 Byte[] _data = new Byte[len]; 29 Marshal.Copy(data, _data, 0, len); 30 31 // Log 32 Console.WriteLine("// usr subscription //_____________________________________"); 33 for (int i = 0; i < _data.Length; i++) Console.Write(string.Format("{0:x2} ", _data[i])); 34 Console.WriteLine(); 35 } 36 37 static void Main(string[] args) 38 { 39 //Open(0x0b6a, 0x5346); 40 //Notify(() => Console.WriteLine("______________device arrival."), 41 // () => Console.WriteLine("__________________device removed."), 42 // ReadData); 43 Hidlib hidlib = new Hidlib(0x0b6a, 0x5346); 44 hidlib.NotifyEvents(() => Console.WriteLine("______________device arrival."), 45 () => Console.WriteLine("__________________device removed."), 46 ReadData); 47 48 while (true) 49 { 50 ConsoleKeyInfo keyInfo = Console.ReadKey(); 51 if (keyInfo.Key == ConsoleKey.Q) 52 { 53 break; 54 } 55 else if (keyInfo.Key == ConsoleKey.W) 56 { 57 Byte[] buffer = new Byte[65]; 58 // ab 69 42 01 fe aa 00 00 aa cd 59 int i = 0; 60 buffer[i++] = 0; 61 buffer[i++] = 0xab; 62 buffer[i++] = 0x69; 63 buffer[i++] = 0x42; 64 buffer[i++] = 0x01; 65 buffer[i++] = 0xfe; 66 buffer[i++] = 0xaa; 67 buffer[i++] = 0x00; 68 buffer[i++] = 0x00; 69 buffer[i++] = 0xaa; 70 buffer[i++] = 0xcd; 71 hidlib.Write(buffer); 72 } 73 } 74 } 75 } 76 }
- Standard C++中的使用
1 // ZSHidWin32App.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include "../ZSHidlib/Hidlib.h" 6 #include "../ZSHidlib/Hidimpl.h" 7 8 #pragma comment(lib, "../Debug/ZSHidlib.lib") 9 10 void Arrival() 11 { 12 printf("______________________device arrival.\n"); 13 } 14 15 void Removed() 16 { 17 printf("______________________device removed.\n"); 18 } 19 20 void ReadData(unsigned char *data, int len) 21 { 22 for (int i = 0; i < len; i++) 23 { 24 printf("%.2x ", data[i]); 25 } 26 printf("___________________call in ReadData callback function."); 27 } 28 29 int _tmain(int argc, _TCHAR* argv[]) 30 { 31 Hidimpl *hidImpl = new Hidimpl(0x0b6a, 0x5346); 32 hidImpl->NotifyEvents(Arrival, Removed, ReadData); 33 34 while(true) 35 { 36 unsigned char buffer[65] = {0x00, 0xab, 0x69, 0x42, 0x01, 0xfe, 0xaa, 0x00, 0x00, 0xaa, 0xcd}; 37 hidImpl->Write(buffer, 65); 38 39 Sleep(5000); 40 } 41 42 system("pause"); 43 44 return 0; 45 }
- 参考书籍/资料
《Visual C++/CLI从入门到精通》
《NET互操作 P_Invoke,C++Interop和COM Interop》