235 lines
6.9 KiB
C
235 lines
6.9 KiB
C
|
#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"
|
|||
|
|
|||
|
// 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<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_;
|
|||
|
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<std::string>& 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)
|
|||
|
//
|