创建线程消息循环服务于动态连接库

因为动态连接库需要对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, &notificationFilter, 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 }

涉及的一些内容:

  1. 线程中CreateWindowEx的调用
  2. 在CreateWindowEx中使用HWND_MESSAGE的作用
  3. 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, &notificationFilter, 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 }
View Code

IO操作情况还是比较理想的!


原文地址:https://www.cnblogs.com/linxmouse/p/7842533.html