#pragma once // implements USB as libusb on windows // // Date: 2022-04-01 #include #include #include #include #include #include #include #include "libusb-1.0/libusb.h" // HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{6bdd1fc6-810f-11d0-bec7-08002be2092f} #define HG_SCANNER_GUID "6BDD1FC6-810F-11D0-BEC7-08002BE2092F" #define MONITOR_WINDOW_OWNER L"monitor_wnd_owner" typedef struct _dev_id { int vid; int pid; bool operator==(const struct _dev_id& r) { return vid == r.vid && pid == r.pid; } }DEVID; class usb_device // consider as libusb_device { volatile long ref_; GUID guid_; std::string name_; DEVID id_; bool is_ok_; bool online_; uint8_t port_; enum { OVL_BULK_IN, OVL_BULK_OUT, OVL_CONTROL, OVL_INTERRUPT, OVL_MAX, }; OVERLAPPED ovl_[OVL_MAX]; libusb_device_handle *handle_; // as file handle returned by CreateFile libusb_device_descriptor *dev_desc_; std::vector cfg_desc_; typedef struct _usb_pipe { UCHAR address; int type; HANDLE pipe; }USBPIPE; std::vector pipes_; DWORD timout_ms_; HANDLE find_pipe(UCHAR addr, int type); int set_timeout(HANDLE h); public: usb_device(const char* name); static DEVID vid_pid_from_name(const char* name); // device name like '\\?\usb#vid_3072&pid_0239#01234567aabbccddee#{a5dcbf10-6530-11d2-901f-00c04fb951ed}' static DWORD from_hex_string(const char* hex_str); static std::string driver_key_name(HANDLE file); static std::string parent_hub_path_name(int vid, int pid, int *addr = NULL); static bool find_vid_pid_in_hub(const char* utf8_hub_path_name, int vid, int pid, int *addr/*if *addr is not -1 or NULL, search the device with vid:pid and set the address in addr if it was not null, or-else chekc the device at *addr is vid:pid or not*/); static int get_device_address(const char* device_name, LPGUID lpguid); long add_ref(void); long release(void); protected: ~usb_device(); public: bool operator==(const char* name); bool operator==(const DEVID& id); usb_device& operator=(const DEVID& id); usb_device& operator=(const GUID& guid); std::string name(void); GUID guid(void); DEVID id(void); bool is_ok(void); bool is_open(void); bool is_online(void); void set_online(bool online); uint8_t port(void); bool init(void); void clear(void); void online_statu_changed(bool online); int get_descriptor(libusb_device_descriptor* desc); int get_config_descriptor(int index, libusb_config_descriptor** desc); int open(libusb_device_handle** dev_handle); int close(void); int set_timeout(unsigned milliseconds); int transfer_bulk(unsigned endpoint, unsigned char* data, int* length, unsigned int timeout); int transfer_control(uint8_t type, uint8_t req, uint16_t val, uint16_t ind, unsigned char* data, uint16_t len, unsigned timeout); int transfer_interrupt(unsigned endpoint, unsigned char* data, int* length, unsigned int timeout); }; class usb_callback { libusb_hotplug_callback_fn usb_cb_; void* usb_cb_param_; public: usb_callback(libusb_hotplug_callback_fn cb, void* param); ~usb_callback(); public: void notify(libusb_context* ctx, usb_device* dev, int ev); }; class usb_monitor // consider as libusb_context { std::vector cbs_; std::mutex lock_; std::vector devices_; std::shared_ptr handle_msg_; DWORD handle_msg_id_; std::string cur_dev_name_; volatile bool run_; HWND wnd_monitor_; static LRESULT CALLBACK monitor_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp); static void register_monitor_wnd(const wchar_t* cls); void notify_usb_event(usb_device*& dev, bool arrive); int on_usb_pnp(WPARAM wp, LPARAM lp); void find_usb(std::vector& usb_devs); public: usb_monitor(); ~usb_monitor(); static usb_monitor* usb_monitor_; public: usb_callback* reg_callback(libusb_hotplug_callback_fn cb, void* param); void unreg_callback(usb_callback* cb); void thread_run_device_event_wnd(void); // called in a seperate thread from libusb void thread_handle_device_change_msg(void); // a seperate thread for WM_DEVICECHANGE cannot be blocked void quit(void); }; //1: \\?\usb#vid_0bda&pid_0129#20100201396000000#{a5dcbf10-6530-11d2-901f-00c04fb951ed} // DeviceIoControl error: 31 // USB\VID_0BDA&PID_0129\20100201396000000 // class: USB // desc: Realtek USB 2.0 Card Reader // HID: USB\VID_0BDA&PID_0129&REV_3960 // name: \Device\USBPDO-3 // bus : 1 // addr: 9 // guid: {36fc9e60-c465-11cf-8056-444553540000} // path: PCIROOT(0)#PCI(1400)#USBROOT(0)#USB(9) // //2: \\?\usb#vid_06cb&pid_00ea#9bec419959f6#{a5dcbf10-6530-11d2-901f-00c04fb951ed} // Open error: 5 // USB\VID_06CB&PID_00EA\9BEC419959F6 // class: Biometric // desc: Synaptics UWP WBDI // HID: USB\VID_06CB&PID_00EA&REV_0000 // name: \Device\USBPDO-5 // bus : 1 // addr: 12 // guid: {53d29ef7-377c-4d14-864b-eb3a85769359} // path: PCIROOT(0)#PCI(1400)#USBROOT(0)#USB(12) // //3: \\?\usb#vid_3072&pid_0239#01234567aabbccddee#{a5dcbf10-6530-11d2-901f-00c04fb951ed} // VID: 3072 // PID: 0239 // USB: 4.4 // USB\VID_3072&PID_0239\01234567AABBCCDDEE // class: Image // desc: HUAGOSCAN G200 TWAIN // HID: USB\VID_3072&PID_0239&REV_0404 // name: \Device\USBPDO-7 // bus : 1 // addr: 8 // guid: {6bdd1fc6-810f-11d0-bec7-08002be2092f} // path: PCIROOT(0)#PCI(1400)#USBROOT(0)#USB(8) // //4: \\?\usb#vid_17ef&pid_6100#5&4adfeed&0&6#{a5dcbf10-6530-11d2-901f-00c04fb951ed} // VID: 0000 // PID: 0000 // USB: 0.0 // USB\VID_17EF&PID_6100\5&4ADFEED&0&6 // class: USB // desc: USB Composite Device // HID: USB\VID_17EF&PID_6100&REV_0201 // name: \Device\USBPDO-1 // bus : 1 // addr: 6 // guid: {36fc9e60-c465-11cf-8056-444553540000} // path: PCIROOT(0)#PCI(1400)#USBROOT(0)#USB(6) // //5: \\?\usb#vid_8087&pid_0026#5&4adfeed&0&14#{a5dcbf10-6530-11d2-901f-00c04fb951ed} // DeviceIoControl error: 50 // USB\VID_8087&PID_0026\5&4ADFEED&0&14 // class: Bluetooth // desc: 英特尔(R) 无线 Bluetooth(R) // HID: USB\VID_8087&PID_0026&REV_0002 // name: \Device\USBPDO-4 // bus : 1 // addr: 14 // guid: {e0cbf06c-cd8b-4647-bb8a-263b43f0f974} // path: PCIROOT(0)#PCI(1400)#USBROOT(0)#USB(14) // //6: \\?\usb#vid_17ef&pid_608d#5&4adfeed&0&7#{a5dcbf10-6530-11d2-901f-00c04fb951ed} // Open error: 31 // USB\VID_17EF&PID_608D\5&4ADFEED&0&7 // class: HIDClass // desc: USB 输入设备 // HID: USB\VID_17EF&PID_608D&REV_0100 // name: \Device\USBPDO-2 // bus : 1 // addr: 7 // guid: {745a17a0-74d3-11d0-b6fe-00a0c90f57da} // path: PCIROOT(0)#PCI(1400)#USBROOT(0)#USB(7) //