2022-05-03 08:54:08 +00:00
# pragma once
// implements USB as libusb on windows
//
// Date: 2022-04-01
# include <Windows.h>
# include <vector>
# include <algorithm>
# include <string>
# include <mutex>
# include <thread>
# include <memory>
# include "libusb-1.0/libusb.h"
2022-07-04 08:31:37 +00:00
# include "../../../code_device/hgdriver/hgdev/hg_ipc.h"
2022-05-03 08:54:08 +00:00
// 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 ;
2022-07-04 08:31:37 +00:00
class ovl_cls : public refer
{
OVERLAPPED ovl_ ;
DWORD io_bytes_ ;
public :
ovl_cls ( ) ;
protected :
~ ovl_cls ( ) ;
public :
LPOVERLAPPED over_lapped ( void ) ;
LPDWORD io_bytes ( void ) ;
void reset ( void ) ;
} ;
class ovl_mgr
{
std : : mutex lock_ ;
std : : vector < ovl_cls * > ovls_ ;
public :
ovl_mgr ( ) ;
~ ovl_mgr ( ) ;
public :
ovl_cls * get_ovl ( void ) ;
} ;
2022-05-03 08:54:08 +00:00
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_ ;
2022-07-04 08:31:37 +00:00
ovl_mgr ovl_mgr_ ;
2022-05-03 08:54:08 +00:00
libusb_device_handle * handle_ ; // as file handle returned by CreateFile
libusb_device_descriptor * dev_desc_ ;
std : : vector < libusb_config_descriptor * > cfg_desc_ ;
typedef struct _usb_pipe
{
UCHAR address ;
int type ;
HANDLE pipe ;
} USBPIPE ;
std : : vector < USBPIPE > 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 < usb_callback * > cbs_ ;
std : : mutex lock_ ;
std : : vector < usb_device * > devices_ ;
std : : shared_ptr < std : : thread > handle_msg_ ;
DWORD handle_msg_id_ ;
2022-08-01 02:41:06 +00:00
HWND wnd_monitor_ ;
2022-05-03 08:54:08 +00:00
std : : string cur_dev_name_ ;
volatile bool run_ ;
2022-08-01 02:41:06 +00:00
std : : vector < std : : string > found_usb_devs_ ;
2022-05-03 08:54:08 +00:00
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 < std : : string > & usb_devs ) ;
2022-08-01 02:41:06 +00:00
void find_usb_and_trigger_event ( void ) ;
2022-05-03 08:54:08 +00:00
public :
usb_monitor ( ) ;
~ usb_monitor ( ) ;
static usb_monitor * usb_monitor_ ;
2022-08-01 02:41:06 +00:00
static UINT find_usb_timer_ ; // set when RegisterDeviceNotification failed
2022-05-03 08:54:08 +00:00
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)
//