zoukankan      html  css  js  c++  java
  • 创建线程消息循环服务于动态连接库

    因为动态连接库需要对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操作情况还是比较理想的!


  • 相关阅读:
    Redis 常用模式思路
    MacOS Catalina 10.15 利用shell脚本启动NGINX、MySQL、PHP
    windows上 python有多版本,如何管理,如何区别?
    20180813视频笔记 深度学习基础上篇(1)之必备基础知识点 深度学习基础上篇(2)神经网络模型视频笔记:深度学习基础上篇(3)神经网络案例实战 和 深度学习基础下篇
    20180813视频笔记 深度学习基础上篇(1)之必备基础知识点 深度学习基础上篇(2)神经网络模型
    数据集
    基于深度学习的目标跟踪
    使用GitHub+Hexo建立个人网站,并绑定自己的域名(Ubuntu环境下)
    使用jemdoc制作个人主页
    《2017全球人工智能人才白皮书》发布丨解读世界顶级AI牛人的秘密——腾讯研究院
  • 原文地址:https://www.cnblogs.com/linxmouse/p/7842533.html
Copyright © 2011-2022 走看看