因为动态连接库需要对DBT_DEVICEARRIVAL、DBT_DEVICEREMOVECOMPLETE等消息的处理,所以拿一个不太理想的Hid的动态库片段来说明,说明部分其它代码有不严格的地方,功能性实测末尾有实测的代码片段,不多说直接上代码!
1 // 下列 ifdef 块是创建使从 DLL 导出更简单的 2 // 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 WIN32USB_EXPORTS 3 // 符号编译的。在使用此 DLL 的 4 // 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将 5 // WIN32USB_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的 6 // 符号视为是被导出的。 7 #ifdef WIN32USB_EXPORTS 8 #define WIN32USB_API __declspec(dllexport) 9 #else 10 #define WIN32USB_API __declspec(dllimport) 11 #endif 12 13 #ifdef __cplusplus 14 extern "C"{ 15 #endif 16 17 typedef void(*UsbHandler)(); 18 19 WIN32USB_API void UsbInit(int vid, int pid); 20 WIN32USB_API void UsbNotify(UsbHandler arrival, UsbHandler removed); 21 WIN32USB_API int UsbWrite(unsigned char *dat); 22 WIN32USB_API BOOL UsbRead(unsigned char *dat); 23 WIN32USB_API int InputReportByteLength(); 24 WIN32USB_API int OutputReportByteLength(); 25 WIN32USB_API bool Connected(); 26 WIN32USB_API void UsbFree(); 27 28 #ifdef __cplusplus 29 } 30 #endif
1 // Win32Usb.cpp : 定义 DLL 应用程序的导出函数。 2 // 3 4 #include "stdafx.h" 5 #include "Win32Usb.h" 6 #include <Dbt.h> 7 8 #pragma comment(lib, "hid.lib") 9 #pragma comment(lib, "setupapi.lib") 10 11 bool connected = false; 12 int inputReportByteLength; 13 int outputReportByteLength; 14 15 int usb_vid = 0; 16 int usb_pid = 0; 17 18 HANDLE hUsbWriter = INVALID_HANDLE_VALUE; 19 HANDLE hUsbReader = INVALID_HANDLE_VALUE; 20 21 // 消息循环线程ID 22 DWORD msglooper_tid = 0; 23 HANDLE msgl_handle = INVALID_HANDLE_VALUE; 24 WNDCLASS wndClass = { 0 }; 25 HDEVNOTIFY hDevnotify = INVALID_HANDLE_VALUE; 26 27 UsbHandler UsbArrivalHandler; 28 UsbHandler UsbRemovedHandler; 29 30 OVERLAPPED ovw = {0}; 31 OVERLAPPED ovr = {0}; 32 33 bool UsbFind(); 34 35 WIN32USB_API void UsbInit(int vid, int pid) 36 { 37 usb_vid = vid; 38 usb_pid = pid; 39 40 UsbFind(); 41 } 42 43 bool UsbFind() 44 { 45 GUID guid; 46 HidD_GetHidGuid(&guid); 47 HDEVINFO hdevinfo = SetupDiGetClassDevs(&guid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); 48 49 SP_DEVICE_INTERFACE_DATA device_interface_data; 50 ZeroMemory(&device_interface_data, sizeof(device_interface_data)); 51 device_interface_data.cbSize = sizeof(device_interface_data); 52 53 //SP_DEVINFO_DATA devinfo_data; 54 //devinfo_data.cbSize = sizeof(devinfo_data); 55 //devinfo_data.ClassGuid = guid; 56 57 int device_interface_index = 0; 58 while (SetupDiEnumDeviceInterfaces(hdevinfo, NULL, &guid, device_interface_index, &device_interface_data)) 59 { 60 //SP_DEVICE_INTERFACE_DETAIL_DATA device_interface_detail_data; 61 //ZeroMemory(&device_interface_detail_data, sizeof(device_interface_detail_data)); 62 //device_interface_detail_data.cbSize = sizeof(device_interface_detail_data); 63 DWORD requireSize; 64 SetupDiGetDeviceInterfaceDetail(hdevinfo, &device_interface_data, NULL, 0, &requireSize, NULL); 65 66 PSP_DEVICE_INTERFACE_DETAIL_DATA psp_device_interface_detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(requireSize); 67 psp_device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); 68 if (SetupDiGetDeviceInterfaceDetail(hdevinfo, &device_interface_data, psp_device_interface_detail_data, requireSize, &requireSize, NULL)) 69 { 70 char * _devicePath = psp_device_interface_detail_data->DevicePath; 71 free(psp_device_interface_detail_data); 72 73 HANDLE _hDevice = CreateFile(_devicePath, 74 GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL); 75 if (_hDevice != INVALID_HANDLE_VALUE) 76 { 77 HIDD_ATTRIBUTES hidd_attributes; 78 HidD_GetAttributes(_hDevice, &hidd_attributes); 79 if (hidd_attributes.VendorID == usb_vid && hidd_attributes.ProductID == usb_pid) 80 { 81 PHIDP_PREPARSED_DATA phidp_preparsed_data; 82 HidD_GetPreparsedData(_hDevice, &phidp_preparsed_data); 83 HIDP_CAPS hidp_caps; 84 HidP_GetCaps(phidp_preparsed_data, &hidp_caps); 85 inputReportByteLength = hidp_caps.InputReportByteLength; 86 outputReportByteLength = hidp_caps.OutputReportByteLength; 87 HidD_FreePreparsedData(phidp_preparsed_data); 88 89 hUsbWriter = CreateFile(_devicePath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 90 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); 91 hUsbReader = CreateFile(_devicePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 92 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); 93 94 SetupDiDestroyDeviceInfoList(hdevinfo); 95 CloseHandle(_hDevice); 96 connected = true; 97 return true; 98 } 99 100 CloseHandle(_hDevice); 101 } 102 } 103 104 device_interface_index++; 105 } 106 107 SetupDiDestroyDeviceInfoList(hdevinfo); 108 return false; 109 } 110 111 WIN32USB_API BOOL UsbRead(unsigned char *dat) 112 { 113 if (connected && hUsbReader != INVALID_HANDLE_VALUE) 114 { 115 DWORD read_size; 116 BOOL rt = ReadFile(hUsbReader, dat, inputReportByteLength, &read_size, &ovr); 117 if (!rt) 118 { 119 if (GetLastError() == ERROR_IO_PENDING) 120 { 121 // 此时是否需要对IO状态作处理看需求,处理与否不会影响IO 122 //rt = WaitForSingleObject(hUsbReader, 50); 123 //switch (rt) 124 //{ 125 //case WAIT_OBJECT_0: 126 // cout << "指定的对象处于有信号状态" << endl; 127 // if (GetOverlappedResult(hUsbReader, &ovr, &read_size, FALSE)) 128 // cout << "read " << read_size << " bytes" << endl; 129 // break; 130 //case WAIT_TIMEOUT: 131 // cout << "等待超时" << endl; 132 // break; 133 //case WAIT_FAILED: 134 // cout << "出现错误,CODE [" << GetLastError() << "]" << endl; 135 // break; 136 //case WAIT_ABANDONED: 137 // cout << "当Handle为mutex时,如果拥有mutex的线程在结束时没有释放核心对象会引发此返回值" << endl; 138 // break; 139 //} 140 141 // <网络上如下代码非常多> 142 //WaitForSingleObjectEx(hUsbReader, INFINITE, TRUE); 143 //rt = GetOverlappedResult(hUsbReader, &ovr, &factBytes, FALSE); 144 //return rt; 145 } 146 else 147 { 148 CancelIo(hUsbReader); 149 return FALSE; 150 } 151 } 152 else return TRUE; 153 } 154 155 return FALSE; 156 } 157 158 WIN32USB_API int UsbWrite(unsigned char *dat) 159 { 160 if (connected && hUsbWriter != INVALID_HANDLE_VALUE) 161 { 162 DWORD write_size; 163 BOOL rt = WriteFile(hUsbWriter, dat, outputReportByteLength, &write_size, &ovw); 164 if (!rt) 165 { 166 if (GetLastError() == ERROR_IO_PENDING) 167 { 168 // 此时是否需要对IO状态作处理看需求,处理与否不会影响IO 169 //rt = WaitForSingleObject(hUsbWriter, 50); 170 //switch (rt) 171 //{ 172 //case WAIT_OBJECT_0: 173 // cout << "指定的对象处于有信号状态" << endl; 174 // if (GetOverlappedResult(hUsbWriter, &ovr, &write_size, FALSE)) 175 // cout << "write " << write_size << " bytes" << endl; 176 // break; 177 //case WAIT_TIMEOUT: 178 // cout << "等待超时" << endl; 179 // break; 180 //case WAIT_FAILED: 181 // cout << "出现错误,CODE [" << GetLastError() << "]" << endl; 182 // break; 183 //case WAIT_ABANDONED: 184 // cout << "当Handle为mutex时,如果拥有mutex的线程在结束时没有释放核心对象会引发此返回值" << endl; 185 // break; 186 //} 187 188 // <网络上如下代码非常多> 189 //WaitForSingleObjectEx(hUsbWriter, INFINITE, TRUE); 190 //rt = GetOverlappedResult(hUsbWriter, &ovw, &write_size, FALSE); 191 //if (!rt) return 0; 192 } 193 else 194 { 195 CancelIo(hUsbWriter); 196 return 0; 197 } 198 } 199 return write_size; 200 } 201 202 return 0; 203 } 204 205 WIN32USB_API int InputReportByteLength(){return inputReportByteLength;} 206 WIN32USB_API int OutputReportByteLength(){ return outputReportByteLength; } 207 WIN32USB_API bool Connected(){ return connected; } 208 209 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 210 { 211 if (msg == WM_DEVICECHANGE) 212 { 213 //MessageBox(NULL, TEXT("WM_DEVICECHANGE"), TEXT("WndProc"), MB_OK); 214 //return 0; 215 switch (wParam) 216 { 217 case DBT_DEVICEARRIVAL: 218 //printf("[wndproc]device arrival."); 219 if (!connected) 220 { 221 if (UsbFind()) 222 { 223 if (UsbArrivalHandler != NULL) UsbArrivalHandler(); 224 } 225 } 226 break; 227 case DBT_DEVICEREMOVECOMPLETE: 228 //printf("[wndproc]device remove."); 229 if (connected) 230 { 231 if (!UsbFind()) 232 { 233 connected = false; 234 if (hUsbWriter != INVALID_HANDLE_VALUE) 235 { 236 CloseHandle(hUsbWriter); 237 hUsbWriter = INVALID_HANDLE_VALUE; 238 } 239 if (hUsbReader != INVALID_HANDLE_VALUE) 240 { 241 CloseHandle(hUsbReader); 242 hUsbReader = INVALID_HANDLE_VALUE; 243 } 244 245 if (UsbRemovedHandler != NULL) UsbRemovedHandler(); 246 } 247 } 248 break; 249 default: 250 break; 251 } 252 } 253 254 return DefWindowProc(hWnd, msg, wParam, lParam); 255 } 256 257 void MessageLooper() 258 { 259 GUID guid; 260 HINSTANCE hInstance = reinterpret_cast<HINSTANCE>(GetModuleHandle(NULL)); 261 wndClass.lpfnWndProc = &WndProc; 262 wndClass.lpszClassName = TEXT("Win32Usb"); 263 wndClass.hInstance = hInstance; 264 if (RegisterClass(&wndClass)) 265 { 266 // 注意HWND_MESSAGE的关键使用 267 HWND wnd = CreateWindowEx(0, wndClass.lpszClassName, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, hInstance, NULL); 268 if (wnd != NULL) 269 { 270 HidD_GetHidGuid(&guid); 271 DEV_BROADCAST_DEVICEINTERFACE notificationFilter = { 0 }; 272 notificationFilter.dbcc_size = sizeof(notificationFilter); 273 notificationFilter.dbcc_classguid = guid; 274 notificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; 275 hDevnotify = RegisterDeviceNotification(wnd, ¬ificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE); 276 277 if (hDevnotify != NULL) 278 { 279 MSG msg; 280 if (GetMessage(&msg, NULL, 0, 0) > 0) 281 { 282 TranslateMessage(&msg); 283 DispatchMessage(&msg); 284 } 285 286 connected = false; 287 if (hUsbWriter != INVALID_HANDLE_VALUE) 288 { 289 CloseHandle(hUsbWriter); 290 hUsbWriter = INVALID_HANDLE_VALUE; 291 } 292 if (hUsbReader != INVALID_HANDLE_VALUE) 293 { 294 CloseHandle(hUsbReader); 295 hUsbReader = INVALID_HANDLE_VALUE; 296 } 297 298 UnregisterDeviceNotification(hDevnotify); 299 } 300 DestroyWindow(wnd); 301 UnregisterClass(wndClass.lpszClassName, hInstance); 302 } 303 } 304 } 305 306 WIN32USB_API void UsbNotify(UsbHandler arrival, UsbHandler removed) 307 { 308 UsbArrivalHandler = arrival; 309 UsbRemovedHandler = removed; 310 // 创建线程消息循环 311 msgl_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MessageLooper, NULL, THREAD_PRIORITY_NORMAL, &msglooper_tid); 312 } 313 314 WIN32USB_API void UsbFree() 315 { 316 connected = false; 317 // 关闭仅提供消息循环HWND_MESSAGE标识窗口 318 PostThreadMessage(msglooper_tid, WM_CLOSE, 0, 0); 319 CloseHandle(msgl_handle); 320 }
涉及的一些内容:
- 线程中CreateWindowEx的调用
- 在CreateWindowEx中使用HWND_MESSAGE的作用
- PostThreadMessage与PostMessage使用上区别的地方
下面是与STM32F103 HID实测代码
1 // Win32UsbTest.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include <string> 6 #include <thread> 7 #include <Dbt.h> 8 #include <iostream> 9 using namespace std; 10 11 #pragma comment(lib, "hid.lib") 12 #pragma comment(lib, "setupapi.lib") 13 14 int inputReportByteLength; 15 int outputReportByteLength; 16 bool connected = false; 17 18 int usb_vid = 0; 19 int usb_pid = 0; 20 21 HANDLE hUsb; 22 //HANDLE hUsbWriter = NULL; 23 //HANDLE hUsbReader = NULL; 24 25 // 消息循环线程ID 26 DWORD msgl_tid = 0; 27 HANDLE msgl_handle = NULL; 28 //std::thread msgl_t; 29 WNDCLASS wndClass = { 0 }; 30 HDEVNOTIFY hDevnotify = NULL; 31 32 std::function<void(void)> UsbArrivalHandler; 33 std::function<void(void)> UsbRemovedHandler; 34 35 OVERLAPPED ovw; 36 OVERLAPPED ovr; 37 38 // 这是导出函数的一个示例。 39 int fnWin32Usb(void) 40 { 41 return 42; 42 } 43 44 void UsbArrival() 45 { 46 printf("device arrival."); 47 } 48 49 void UsbRemoved() 50 { 51 printf("device remove."); 52 } 53 54 bool UsbFind() 55 { 56 GUID guid; 57 HidD_GetHidGuid(&guid); 58 HDEVINFO hdevinfo = SetupDiGetClassDevs(&guid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); 59 60 try 61 { 62 SP_DEVICE_INTERFACE_DATA device_interface_data; 63 ZeroMemory(&device_interface_data, sizeof(device_interface_data)); 64 device_interface_data.cbSize = sizeof(device_interface_data); 65 66 //SP_DEVINFO_DATA devinfo_data; 67 //devinfo_data.cbSize = sizeof(devinfo_data); 68 //devinfo_data.ClassGuid = guid; 69 70 int device_interface_index = 0; 71 while (SetupDiEnumDeviceInterfaces(hdevinfo, NULL, &guid, device_interface_index, &device_interface_data)) 72 { 73 //SP_DEVICE_INTERFACE_DETAIL_DATA device_interface_detail_data; 74 //ZeroMemory(&device_interface_detail_data, sizeof(device_interface_detail_data)); 75 //device_interface_detail_data.cbSize = sizeof(device_interface_detail_data); 76 DWORD requireSize; 77 SetupDiGetDeviceInterfaceDetail(hdevinfo, &device_interface_data, NULL, 0, &requireSize, NULL); 78 79 PSP_DEVICE_INTERFACE_DETAIL_DATA psp_device_interface_detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(requireSize); 80 psp_device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); 81 if (SetupDiGetDeviceInterfaceDetail(hdevinfo, &device_interface_data, psp_device_interface_detail_data, requireSize, &requireSize, NULL)) 82 { 83 //std::string _devicePath = psp_device_interface_detail_data->DevicePath; 84 std::wstring _devicePath = psp_device_interface_detail_data->DevicePath; 85 free(psp_device_interface_detail_data); 86 87 HANDLE _hDevice = CreateFile(_devicePath.c_str(), GENERIC_READ, NULL, NULL, OPEN_EXISTING, NULL, NULL); 88 if (_hDevice != INVALID_HANDLE_VALUE) 89 { 90 HIDD_ATTRIBUTES hidd_attributes; 91 HidD_GetAttributes(_hDevice, &hidd_attributes); 92 if (hidd_attributes.VendorID == usb_vid && hidd_attributes.ProductID == usb_pid) 93 { 94 PHIDP_PREPARSED_DATA phidp_preparsed_data; 95 HidD_GetPreparsedData(_hDevice, &phidp_preparsed_data); 96 HIDP_CAPS hidp_caps; 97 HidP_GetCaps(phidp_preparsed_data, &hidp_caps); 98 inputReportByteLength = hidp_caps.InputReportByteLength; 99 outputReportByteLength = hidp_caps.OutputReportByteLength; 100 HidD_FreePreparsedData(phidp_preparsed_data); 101 102 // 先关闭些句柄,否则下面的CreateFile会调用失败 103 CloseHandle(_hDevice); 104 //hUsbWriter = CreateFile(_devicePath.c_str(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL); 105 //hUsbReader = CreateFile(_devicePath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL); 106 hUsb = CreateFile(_devicePath.c_str(), GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); 107 if (hUsb == INVALID_HANDLE_VALUE) cout << "CreateFile-出现错误, CODE[" << GetLastError() << "]" << endl; 108 109 SetupDiDestroyDeviceInfoList(hdevinfo); 110 connected = true; 111 return true; 112 } 113 114 CloseHandle(_hDevice); 115 } 116 } 117 118 device_interface_index++; 119 } 120 } 121 catch (...) 122 { 123 SetupDiDestroyDeviceInfoList(hdevinfo); 124 } 125 126 return false; 127 } 128 129 void UsbInit(int vid, int pid) 130 { 131 usb_vid = vid; 132 usb_pid = pid; 133 if (UsbFind()) cout << "find device where vid = " << vid << " pid = " << pid << endl; 134 } 135 136 int UsbWrite(unsigned char *bytes) 137 { 138 if (connected) 139 { 140 DWORD write_size = 0; 141 //WriteFile(hUsbWriter, bytes, outputReportByteLength, &write_size, NULL); 142 //return factBytes; 143 BOOL rt = WriteFile(hUsb, bytes, outputReportByteLength, &write_size, &ovw); 144 if (!rt) 145 { 146 if (GetLastError() == ERROR_IO_PENDING) 147 { 148 // 此时是否需要对IO状态作处理看需求,处理与否不会影响IO 149 //rt = WaitForSingleObject(hUsb, 50); 150 //switch (rt) 151 //{ 152 //case WAIT_OBJECT_0: 153 // cout << "指定的对象处于有信号状态" << endl; 154 // if (GetOverlappedResult(hUsb, &ovr, &write_size, FALSE)) 155 // cout << "write " << write_size << " bytes" << endl; 156 // break; 157 //case WAIT_TIMEOUT: 158 // cout << "等待超时" << endl; 159 // break; 160 //case WAIT_FAILED: 161 // cout << "出现错误,CODE [" << GetLastError() << "]" << endl; 162 // break; 163 //case WAIT_ABANDONED: 164 // cout << "当Handle为mutex时,如果拥有mutex的线程在结束时没有释放核心对象会引发此返回值" << endl; 165 // break; 166 //} 167 168 // <网络上此类代码非常多-个人不推荐> 169 //WaitForSingleObjectEx(hUsbWriter, INFINITE, TRUE); 170 //rt = GetOverlappedResult(hUsbWriter, &ovw, &write_size, FALSE); 171 //if (!rt) return 0; 172 } 173 else 174 { 175 cout << "WriteFile-出现错误, CODE [" << GetLastError() << "]" << endl; 176 CancelIo(hUsb); 177 return 0; 178 } 179 } 180 return write_size; 181 } 182 183 return 0; 184 } 185 186 int UsbRead(unsigned char *dat) 187 { 188 DWORD error; 189 DWORD read_size = 0; 190 if (connected) 191 { 192 //ReadFile(hUsbReader, dat, inputReportByteLength, &factBytes, NULL); 193 //return true; 194 BOOL rt = ReadFile(hUsb, dat, inputReportByteLength, &read_size, &ovr); 195 if (!rt) 196 { 197 if (GetLastError() == ERROR_IO_PENDING) 198 { 199 // 此时是否需要对IO状态作处理看需求,处理与否不会影响IO 200 // 针对此类HID这里是必须的-否则ReadFile会有1453的错误[配额不足,无法完成请求的服务] 201 rt = WaitForSingleObject(hUsb, 50); 202 switch (rt) 203 { 204 case WAIT_OBJECT_0: 205 //cout << "指定的对象处于有信号状态" << endl; 206 // 针对此类HID此处不可省略 207 rt = GetOverlappedResult(hUsb, &ovr, &read_size, FALSE); 208 if (!rt) 209 { 210 //if (GetLastError() == ERROR_IO_INCOMPLETE) 211 //{ 212 // // just wait 213 //} 214 //else 215 //{ 216 // cout << "出现错误,CODE [" << GetLastError() << "]" << endl; 217 //} 218 if (GetLastError() != ERROR_IO_INCOMPLETE) 219 { 220 cout << "出现错误,CODE [" << GetLastError() << "]" << endl; 221 } 222 } 223 else 224 { 225 //cout << "GetOverlappedResult return read size = " << read_size << endl; 226 return read_size; 227 } 228 break; 229 case WAIT_TIMEOUT: 230 //ResetEvent(ovr.hEvent); 231 //cout << "等待超时" << endl; 232 break; 233 case WAIT_FAILED: 234 cout << "出现错误,CODE [" << GetLastError() << "]" << endl; 235 break; 236 case WAIT_ABANDONED: 237 cout << "当Handle为mutex时,如果拥有mutex的线程在结束时没有释放核心对象会引发此返回值" << endl; 238 break; 239 } 240 241 // <网络上此类代码非常多-个人不推荐> 242 //WaitForSingleObjectEx(hUsbReader, INFINITE, TRUE); 243 //rt = GetOverlappedResult(hUsbReader, &ovr, &factBytes, FALSE); 244 //return rt; 245 } 246 else 247 { 248 cout << "ReadFile-出现错误, CODE [" << GetLastError() << "]" << endl; 249 CancelIo(hUsb); 250 return 0; 251 } 252 } 253 else return read_size; 254 } 255 256 return read_size; 257 } 258 259 int InputReportByteLength(){ return inputReportByteLength; } 260 int OutputReportByteLength(){ return outputReportByteLength; } 261 bool Connected(){ return connected; } 262 263 void read_worker_t() 264 { 265 cout << "read_worker_t start." << endl; 266 267 unsigned char buf[65]; 268 while (true) 269 { 270 if (UsbRead(buf) > 0) 271 { 272 for (int i = 0; i < 65; i++) 273 { 274 printf("%2x ", buf[i]); 275 } 276 //std::this_thread::sleep_for(std::chrono::milliseconds(500)); 277 } 278 } 279 } 280 281 void write_worker_t() 282 { 283 //printf("write_worker_t start."); 284 cout << "write_worker_t start." << endl; 285 286 unsigned char buf[65] = { 0 }; 287 buf[0] = 0; 288 buf[1] = 1; 289 buf[2] = 2; 290 buf[3] = 3; 291 buf[4] = 4; 292 buf[5] = 5; 293 buf[6] = 6; 294 buf[7] = 7; 295 buf[8] = 8; 296 buf[9] = 9; 297 buf[10] = 10; 298 while (true) 299 { 300 UsbWrite(buf); 301 std::this_thread::sleep_for(std::chrono::milliseconds(1000)); 302 } 303 } 304 305 LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam) 306 { 307 if (uiMsg == WM_DEVICECHANGE) 308 { 309 //MessageBox(NULL, TEXT("WM_DEVICECHANGE"), TEXT("WndProc"), MB_OK); 310 //return 0; 311 switch (wParam) 312 { 313 case DBT_DEVICEARRIVAL: 314 //printf("[wndproc]device arrival."); 315 if (!connected) 316 { 317 if (UsbFind()) 318 { 319 if (UsbArrivalHandler != nullptr) UsbArrivalHandler(); 320 } 321 } 322 break; 323 case DBT_DEVICEREMOVECOMPLETE: 324 //printf("[wndproc]device remove."); 325 if (connected) 326 { 327 if (!UsbFind()) 328 { 329 connected = false; 330 //CancelIo(hUsbWriter); 331 //CloseHandle(hUsbWriter); 332 //CancelIo(hUsbReader); 333 //CloseHandle(hUsbReader); 334 CancelIo(hUsb); 335 CloseHandle(hUsb); 336 hUsb = INVALID_HANDLE_VALUE; 337 338 if (UsbRemovedHandler != nullptr) UsbRemovedHandler(); 339 } 340 } 341 break; 342 default: 343 break; 344 } 345 } 346 347 return DefWindowProc(hWnd, uiMsg, wParam, lParam); 348 } 349 350 void MessageLoop() 351 { 352 GUID guid; 353 HINSTANCE hInstance = reinterpret_cast<HINSTANCE>(GetModuleHandle(NULL)); 354 wndClass.lpfnWndProc = &WndProc; 355 wndClass.lpszClassName = TEXT("Win32Usb"); 356 wndClass.hInstance = hInstance; 357 if (RegisterClass(&wndClass)) 358 { 359 HWND wnd = CreateWindowEx(0, wndClass.lpszClassName, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, hInstance, NULL); 360 if (wnd != NULL) 361 { 362 HidD_GetHidGuid(&guid); 363 DEV_BROADCAST_DEVICEINTERFACE notificationFilter = { 0 }; 364 notificationFilter.dbcc_size = sizeof(notificationFilter); 365 notificationFilter.dbcc_classguid = guid; 366 notificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; 367 hDevnotify = RegisterDeviceNotification(wnd, ¬ificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE); 368 369 if (hDevnotify != NULL) 370 { 371 MSG msg; 372 if (GetMessage(&msg, NULL, 0, 0) > 0) 373 { 374 TranslateMessage(&msg); 375 DispatchMessage(&msg); 376 } 377 378 printf("message loop end."); 379 UnregisterDeviceNotification(hDevnotify); 380 } 381 DestroyWindow(wnd); 382 UnregisterClass(wndClass.lpszClassName, hInstance); 383 } 384 } 385 } 386 387 void UsbNotify(const std::function<void(void)> &arrival, const std::function<void(void)> &removed) 388 { 389 std::this_thread::sleep_for(std::chrono::milliseconds(500)); 390 391 UsbArrivalHandler = arrival; 392 UsbRemovedHandler = removed; 393 394 msgl_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MessageLoop, NULL, THREAD_PRIORITY_NORMAL, &msgl_tid); 395 } 396 397 void UsbFree() 398 { 399 //CancelIo(hUsbWriter); 400 //CloseHandle(hUsbWriter); 401 //CancelIo(hUsbReader); 402 //CloseHandle(hUsbReader); 403 CancelIo(hUsb); 404 CloseHandle(hUsb); 405 hUsb = INVALID_HANDLE_VALUE; 406 407 //SendMessage(win32usbWnd, WM_CLOSE, 0, 0); 408 PostThreadMessage(msgl_tid, WM_CLOSE, 0, 0); 409 SleepEx(50, FALSE); 410 CloseHandle(msgl_handle); 411 } 412 413 int _tmain(int argc, _TCHAR* argv[]) 414 { 415 UsbInit(0x0483, 0x5750); 416 UsbNotify(UsbArrival, UsbRemoved); 417 418 std::thread read_t(read_worker_t); 419 std::thread write_t(write_worker_t); 420 421 cout << "In main thread." << endl; 422 while (true) 423 { 424 std::this_thread::sleep_for(std::chrono::milliseconds(15000)); 425 } 426 return 0; 427 }
IO操作情况还是比较理想的!