code_twain/device/win_usb/win_usb.h

259 lines
7.4 KiB
C
Raw Normal View History

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"
#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;
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_;
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)
//