code_twain/device/win_usb/win_usb.cpp

1526 lines
46 KiB
C++
Raw Permalink Normal View History

2022-05-03 08:54:08 +00:00
#include "win_usb.h"
#include <initguid.h>
#include <usbiodef.h>
#include <usbioctl.h>
#include <SetupAPI.h>
#include <hidsdi.h>
#include <winusb.h>
#include <rpc.h>
//#include <winioctl.h>
#include <usbscan.h>
#include <Dbt.h>
#pragma comment(lib, "setupapi.lib")
#pragma comment(lib, "hid.lib")
#pragma comment(lib, "winusb.lib")
#pragma comment(lib, "rpcrt4.lib")
2022-08-11 10:05:01 +00:00
#pragma comment(lib, "advapi32.lib") // for Reg...
2022-05-03 08:54:08 +00:00
2023-04-23 07:56:21 +00:00
//#if defined(OEM_NONE) || defined(OEM_LISCHENG) || defined(OEM_HANWANG)|| defined(OEM_ZHONGJING)
#include "../wrapper/hg_log.h"
2023-04-23 07:56:21 +00:00
//#else
//#define VLOG_MINI_1(l, f, d) printf(f, d)
//#define VLOG_MINI_2(l, f, d1, d2) printf(f, d1, d2)
//#define VLOG_MINI_3(l, f, d1, d2, d3) printf(f, d1, d2, d3)
//#define VLOG_MINI_4(l, f, d1, d2, d3, d4) printf(f, d1, d2, d3, d4)
//#endif
2022-05-03 08:54:08 +00:00
#include "usbview/enum.h"
2022-10-12 06:31:08 +00:00
#include "../../../sdk/include/huagao/brand.h"
2022-08-11 10:05:01 +00:00
#pragma warning(disable: 4996)
2022-05-03 08:54:08 +00:00
#define MSG_DEVICE_PNP WM_USER + 1 // wParam: (bool)arrive; lParam: usb_device*
#define bzero(a, l) memset(a, 0, l)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// usb_callback ...
usb_callback::usb_callback(libusb_hotplug_callback_fn cb
, void* param)
: usb_cb_(cb), usb_cb_param_(param)
{}
usb_callback::~usb_callback()
{}
void usb_callback::notify(libusb_context* ctx, usb_device* dev, int ev)
{
usb_cb_(ctx, (libusb_device*)dev, (libusb_hotplug_event)ev, usb_cb_param_);
}
std::string u2utf8(const wchar_t* u)
{
2023-02-02 06:22:05 +00:00
#if defined(OEM_NONE) || defined(OEM_LISCHENG) || defined(OEM_HANWANG) || defined(OEM_ZHONGJING)
2022-05-03 08:54:08 +00:00
return hg_log::u2utf8(u);
2022-08-11 10:05:01 +00:00
#else
2023-04-21 06:29:30 +00:00
int len = WideCharToMultiByte(CP_UTF8, 0, u, lstrlenW(u), NULL, 0, NULL, NULL);
char* ansi = new char[len + 4];
2022-05-03 08:54:08 +00:00
2023-04-21 06:29:30 +00:00
len = WideCharToMultiByte(CP_UTF8, 0, u, lstrlenW(u), ansi, len, NULL, NULL);
ansi[len--] = 0;
2022-05-03 08:54:08 +00:00
2023-04-21 06:29:30 +00:00
std::string utf8(ansi);
delete[] ansi;
return utf8;
2022-08-11 10:05:01 +00:00
#endif
2022-05-03 08:54:08 +00:00
}
2022-08-11 10:05:01 +00:00
std::wstring ansi2unicode(const char* ansi, UINT cp = CP_ACP)
{
int len = MultiByteToWideChar(cp, 0, ansi, lstrlenA(ansi), NULL, 0);
wchar_t* buf = new wchar_t[len + 4];
memset(buf, 0, (len + 4) * 2);
len = MultiByteToWideChar(cp, 0, ansi, lstrlenA(ansi), buf, len);
buf[len--] = 0;
std::wstring unic(buf);
delete[] buf;
2022-05-03 08:54:08 +00:00
2022-08-11 10:05:01 +00:00
return unic;
}
std::string unicode2ansi(const wchar_t* unic, UINT cp = CP_ACP)
{
int len = WideCharToMultiByte(cp, 0, unic, lstrlenW(unic), NULL, 0, NULL, NULL);
char *buf = new char[len + 4];
memset(buf, 0, len + 4);
len = WideCharToMultiByte(cp, 0, unic, lstrlenW(unic), buf, len, NULL, NULL);
buf[len--] = 0;
std::string ansi(buf);
delete[] buf;
return ansi;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// OVERLAPPED ...
2023-04-21 06:29:30 +00:00
ovl_cls::ovl_cls() : ref_(1), io_bytes_(0)
{
memset(&ovl_, 0, sizeof(ovl_));
ovl_.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
}
ovl_cls::~ovl_cls()
{
CloseHandle(ovl_.hEvent);
}
LPOVERLAPPED ovl_cls::over_lapped(void)
{
return &ovl_;
}
LPDWORD ovl_cls::io_bytes(void)
{
return &io_bytes_;
}
void ovl_cls::reset(void)
{
HANDLE h = ovl_.hEvent;
memset(&ovl_, 0, sizeof(ovl_));
ovl_.hEvent = h;
io_bytes_ = 0;
ResetEvent(h);
}
bool ovl_cls::is_waited(void)
{
return WaitForSingleObject(ovl_.hEvent, 0) == WAIT_OBJECT_0;
}
ovl_mgr::ovl_mgr()
{}
ovl_mgr::~ovl_mgr()
{
for (auto& v : ovls_)
v->release();
}
2023-04-21 06:29:30 +00:00
ovl_cls* ovl_mgr::get_ovl(void)
{
std::lock_guard<std::mutex> lock(lock_);
ovl_cls* o = NULL;
for (auto& v : ovls_)
{
2023-04-21 06:29:30 +00:00
if (v->is_waited())
{
o = v;
o->add_ref();
o->reset();
break;
}
}
if (!o)
{
2023-04-21 06:29:30 +00:00
o = new ovl_cls();
ovls_.push_back(o);
o->add_ref();
}
return o;
}
2022-05-03 08:54:08 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// usb_device ...
usb_device::usb_device(const USBDEV& dev) : ref_(1), udev_(dev), is_ok_(false)
2023-04-21 06:29:30 +00:00
, dev_desc_(NULL), handle_(NULL), online_(true), timout_ms_(1000)
2022-05-03 08:54:08 +00:00
{
memset(&guid_, 0, sizeof(guid_));
2022-05-03 08:54:08 +00:00
}
usb_device::~usb_device()
{
clear();
}
2022-08-09 07:08:50 +00:00
HANDLE usb_device::find_pipe(UCHAR addr, int type, int* index)
2022-05-03 08:54:08 +00:00
{
for (size_t i = 0; i < pipes_.size(); ++i)
{
if (pipes_[i].address == addr && pipes_[i].type == type)
2022-08-09 07:08:50 +00:00
{
if (index)
*index = i;
2022-05-03 08:54:08 +00:00
return pipes_[i].pipe;
2022-08-09 07:08:50 +00:00
}
2022-05-03 08:54:08 +00:00
}
return NULL;
}
2022-08-11 10:05:01 +00:00
HANDLE usb_device::open_usb(const char* usb_name, DWORD access, DWORD share)
2022-08-09 09:07:39 +00:00
{
2022-08-11 10:05:01 +00:00
std::wstring unic(ansi2unicode(usb_name));
SECURITY_ATTRIBUTES sa = { 0 };
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
return CreateFileW(unic.c_str(), access, share, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
2022-08-09 09:07:39 +00:00
}
2022-05-03 08:54:08 +00:00
int usb_device::set_timeout(HANDLE h)
{
USBSCAN_TIMEOUT uto = { 0 };
DWORD cbr = 0;
uto.TimeoutEvent = uto.TimeoutRead = uto.TimeoutWrite = (timout_ms_ + 500) / 1000;
2023-04-21 06:29:30 +00:00
2022-05-03 08:54:08 +00:00
return DeviceIoControl(h, IOCTL_SET_TIMEOUT, &uto, sizeof(uto), NULL, 0, &cbr, NULL) ? LIBUSB_SUCCESS : LIBUSB_ERROR_IO;
2022-08-11 10:05:01 +00:00
//COMMTIMEOUTS to = { 0 };
//to.ReadIntervalTimeout = timout_ms_;
//to.ReadTotalTimeoutConstant = timout_ms_;
//to.ReadTotalTimeoutMultiplier = 1;
//
//SetCommTimeouts(h, &to);
2022-05-03 08:54:08 +00:00
}
void usb_device::vid_pid_from_name(const char* name, int* vid, int* pid)
2022-05-03 08:54:08 +00:00
{
2023-04-21 06:29:30 +00:00
// name: \\?\usb#vid_3072&pid_0239#01234567aabbccddee#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
std::string s(name ? name : "");
size_t pos = 0;
2022-05-03 08:54:08 +00:00
2023-04-21 06:29:30 +00:00
std::transform(s.begin(), s.end(), s.begin(), tolower);
pos = s.find("vid_");
if (pos != std::string::npos && vid)
*vid = usb_device::from_hex_string(s.c_str() + pos + 4);
2022-05-03 08:54:08 +00:00
2023-04-21 06:29:30 +00:00
pos = s.find("pid_");
if (pos != std::string::npos && pid)
*pid = usb_device::from_hex_string(s.c_str() + pos + 4);
2022-05-03 08:54:08 +00:00
}
DWORD usb_device::from_hex_string(const char* hex_str)
{
2023-04-21 06:29:30 +00:00
DWORD v = 0;
2022-05-03 08:54:08 +00:00
2023-04-21 06:29:30 +00:00
for (int i = 0; hex_str[i]; ++i)
{
DWORD now = 0;
if (hex_str[i] >= '0' && hex_str[i] <= '9')
now = hex_str[i] - '0';
else if (hex_str[i] >= 'a' && hex_str[i] <= 'f')
now = hex_str[i] - 'a' + 10;
else if (hex_str[i] >= 'A' && hex_str[i] <= 'F')
now = hex_str[i] - 'A' + 10;
else
break;
2022-05-03 08:54:08 +00:00
2023-04-21 06:29:30 +00:00
v <<= 4;
v += now;
}
2022-05-03 08:54:08 +00:00
2023-04-21 06:29:30 +00:00
return v;
2022-05-03 08:54:08 +00:00
}
std::string usb_device::name_without_guid(const char* name)
2022-05-03 08:54:08 +00:00
{
std::string no_guid(name);
size_t pos = no_guid.find("#{");
2022-05-03 08:54:08 +00:00
if (pos != std::string::npos)
no_guid.erase(pos);
2022-05-03 08:54:08 +00:00
return no_guid;
2022-08-11 10:05:01 +00:00
}
std::string usb_device::usb_scan_name(const char* reg_key)
{
std::wstring path(L"SYSTEM\\CurrentControlSet\\Control\\Class\\" + ansi2unicode(reg_key, CP_UTF8));
HKEY key = NULL;
int err = RegOpenKeyW(HKEY_LOCAL_MACHINE, path.c_str(), &key);
std::string ret("");
if (key)
{
char val[256] = { 0 };
DWORD len = _countof(val) - 1,
2023-04-21 06:29:30 +00:00
type = REG_SZ;
if (RegQueryValueExW(key, L"CreateFileName", NULL, &type, (LPBYTE)val, &len) == ERROR_SUCCESS)
{
val[len] = 0;
ret = u2utf8((wchar_t*)val);
}
RegCloseKey(key);
}
return ret;
}
2022-05-03 08:54:08 +00:00
long usb_device::add_ref(void)
{
return InterlockedIncrement(&ref_);
}
long usb_device::release(void)
{
long ref = InterlockedDecrement(&ref_);
if (ref == 0)
delete this;
return ref;
}
usb_device& usb_device::operator=(const GUID& guid)
{
guid_ = guid;
return *this;
}
std::string usb_device::name(void)
{
return udev_.name;
2022-05-03 08:54:08 +00:00
}
USBDEV& usb_device::dev(void)
2022-05-03 08:54:08 +00:00
{
return udev_;
2022-05-03 08:54:08 +00:00
}
GUID usb_device::guid(void)
2022-05-03 08:54:08 +00:00
{
return guid_;
2022-05-03 08:54:08 +00:00
}
bool usb_device::is_ok(void)
{
2023-04-21 06:29:30 +00:00
return is_ok_;
2022-05-03 08:54:08 +00:00
}
bool usb_device::is_open(void)
{
return handle_ != NULL;
}
bool usb_device::is_online(void)
{
return online_;
}
void usb_device::set_online(bool online)
{
online_ = online;
}
uint8_t usb_device::port(void)
{
if (!dev_desc_)
init();
return udev_.port;
}
uint8_t usb_device::address(void)
{
if (!dev_desc_)
init();
return udev_.addr;
2022-05-03 08:54:08 +00:00
}
2022-10-19 06:00:23 +00:00
std::string usb_device::reg_path(void)
{
return udev_.driver_key;
2022-10-19 06:00:23 +00:00
}
2022-05-03 08:54:08 +00:00
bool usb_device::init(void)
{
PUSBDEVICEINFO info = NULL;
GUID guid;
clear();
usb_monitor::enum_usb_device(&usb_monitor::find_parent_hub, &udev_, true);
VLOG_MINI_3(LOG_LEVEL_ALL, "Device '%s' at hub '%s + %d'\r\n", udev_.name.c_str(), udev_.hub.c_str(), udev_.port);
if (!udev_.hub.empty())
2022-05-03 08:54:08 +00:00
{
HANDLE h = CreateFileA(udev_.hub.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (h != INVALID_HANDLE_VALUE)
2022-05-03 08:54:08 +00:00
{
info = enumerate_hub_port(h, udev_.port);
CloseHandle(h);
2022-05-03 08:54:08 +00:00
}
}
#define COPY_MEMBER(d, s, m) \
(d)->m = (s)->m
if (info)
{
udev_.addr = info->ConnectionInfo->DeviceAddress;
2022-05-03 08:54:08 +00:00
if (info->ConnectionInfo)
{
dev_desc_ = new libusb_device_descriptor;
COPY_MEMBER(dev_desc_, &info->ConnectionInfo->DeviceDescriptor, bLength);
COPY_MEMBER(dev_desc_, &info->ConnectionInfo->DeviceDescriptor, bDescriptorType);
COPY_MEMBER(dev_desc_, &info->ConnectionInfo->DeviceDescriptor, bcdUSB);
COPY_MEMBER(dev_desc_, &info->ConnectionInfo->DeviceDescriptor, bDeviceClass);
COPY_MEMBER(dev_desc_, &info->ConnectionInfo->DeviceDescriptor, bDeviceSubClass);
COPY_MEMBER(dev_desc_, &info->ConnectionInfo->DeviceDescriptor, bDeviceProtocol);
COPY_MEMBER(dev_desc_, &info->ConnectionInfo->DeviceDescriptor, bMaxPacketSize0);
COPY_MEMBER(dev_desc_, &info->ConnectionInfo->DeviceDescriptor, idVendor);
COPY_MEMBER(dev_desc_, &info->ConnectionInfo->DeviceDescriptor, idProduct);
COPY_MEMBER(dev_desc_, &info->ConnectionInfo->DeviceDescriptor, bcdDevice);
COPY_MEMBER(dev_desc_, &info->ConnectionInfo->DeviceDescriptor, iManufacturer);
COPY_MEMBER(dev_desc_, &info->ConnectionInfo->DeviceDescriptor, iProduct);
COPY_MEMBER(dev_desc_, &info->ConnectionInfo->DeviceDescriptor, iSerialNumber);
COPY_MEMBER(dev_desc_, &info->ConnectionInfo->DeviceDescriptor, bNumConfigurations);
}
PSTRING_DESCRIPTOR_NODE strdesc = info->StringDescs;
while (strdesc)
{
STRCFG sc;
sc.id = strdesc->DescriptorIndex;
sc.val = strdesc->StringDescriptor ? unicode2ansi(strdesc->StringDescriptor->bString) : "";
str_cfg_.push_back(sc);
strdesc = strdesc->Next;
}
2022-05-03 08:54:08 +00:00
if (info->ConfigDesc)
{
libusb_config_descriptor* desc = NULL;
PUSB_COMMON_DESCRIPTOR cmn = (PUSB_COMMON_DESCRIPTOR)(info->ConfigDesc + 1);
2022-08-11 10:05:01 +00:00
int if_ind = 0, ep_ind = 0, used = 0;
2022-05-03 08:54:08 +00:00
2022-08-11 10:05:01 +00:00
while (used < info->ConfigDesc->SetupPacket.wLength && cmn->bLength)
2022-05-03 08:54:08 +00:00
{
if (USB_CONFIGURATION_DESCRIPTOR_TYPE == cmn->bDescriptorType)
{
PUSB_CONFIGURATION_DESCRIPTOR conf = (PUSB_CONFIGURATION_DESCRIPTOR)cmn;
if (desc)
cfg_desc_.push_back(desc);
desc = new libusb_config_descriptor;
memset(desc, 0, sizeof(*desc));
COPY_MEMBER(desc, conf, bLength);
COPY_MEMBER(desc, conf, bDescriptorType);
COPY_MEMBER(desc, conf, wTotalLength);
COPY_MEMBER(desc, conf, bNumInterfaces);
COPY_MEMBER(desc, conf, bConfigurationValue);
COPY_MEMBER(desc, conf, iConfiguration);
COPY_MEMBER(desc, conf, bmAttributes);
COPY_MEMBER(desc, conf, MaxPower);
desc->usb_if = new libusb_interface[desc->bNumInterfaces];
memset(desc->usb_if, 0, desc->bNumInterfaces * sizeof(desc->usb_if[0]));
ep_ind = if_ind = 0;
}
else if (USB_INTERFACE_DESCRIPTOR_TYPE == cmn->bDescriptorType)
{
PUSB_INTERFACE_DESCRIPTOR ifd = (PUSB_INTERFACE_DESCRIPTOR)cmn;
libusb_interface_descriptor* uid = NULL;
desc->usb_if[if_ind].num_altsetting = 1;
desc->usb_if[if_ind].altsetting = uid = new libusb_interface_descriptor;
2022-08-09 07:08:50 +00:00
memset(uid, 0, sizeof(libusb_interface_descriptor));
2022-05-03 08:54:08 +00:00
COPY_MEMBER(uid, ifd, bLength);
COPY_MEMBER(uid, ifd, bDescriptorType);
COPY_MEMBER(uid, ifd, bInterfaceNumber);
COPY_MEMBER(uid, ifd, bAlternateSetting);
COPY_MEMBER(uid, ifd, bNumEndpoints);
COPY_MEMBER(uid, ifd, bInterfaceClass);
COPY_MEMBER(uid, ifd, bInterfaceSubClass);
COPY_MEMBER(uid, ifd, bInterfaceProtocol);
COPY_MEMBER(uid, ifd, iInterface);
uid->endpoint = new libusb_endpoint_descriptor[desc->usb_if[if_ind].altsetting->bNumEndpoints];
if_ind++;
ep_ind = 0;
}
else if (USB_ENDPOINT_DESCRIPTOR_TYPE == cmn->bDescriptorType)
{
PUSB_ENDPOINT_DESCRIPTOR endp = (PUSB_ENDPOINT_DESCRIPTOR)cmn;
libusb_endpoint_descriptor* uep = (libusb_endpoint_descriptor*)((void*)&desc->usb_if[if_ind - 1].altsetting->endpoint[ep_ind]);
2022-08-09 07:08:50 +00:00
memset(uep, 0, sizeof(*uep));
2022-05-03 08:54:08 +00:00
COPY_MEMBER(uep, endp, bLength);
COPY_MEMBER(uep, endp, bDescriptorType);
COPY_MEMBER(uep, endp, bEndpointAddress);
COPY_MEMBER(uep, endp, bmAttributes);
COPY_MEMBER(uep, endp, wMaxPacketSize);
COPY_MEMBER(uep, endp, bInterval);
ep_ind++;
}
2022-08-11 10:05:01 +00:00
used += cmn->bLength;
2022-05-03 08:54:08 +00:00
cmn = (PUSB_COMMON_DESCRIPTOR)((PCHAR)cmn + cmn->bLength);
}
if (desc)
cfg_desc_.push_back(desc);
is_ok_ = !cfg_desc_.empty();
}
free_usb_device_info(info);
}
return is_ok_;
}
void usb_device::clear(void)
{
close();
str_cfg_.clear();
2022-05-03 08:54:08 +00:00
if (dev_desc_)
delete dev_desc_;
dev_desc_ = NULL;
for (size_t i = 0; i < cfg_desc_.size(); ++i)
{
if (cfg_desc_[i]->usb_if)
{
for (size_t j = 0; j < cfg_desc_[i]->bNumInterfaces; ++j)
{
if (cfg_desc_[i]->usb_if[j].altsetting->endpoint)
delete[] cfg_desc_[i]->usb_if[j].altsetting->endpoint;
2023-08-11 06:04:57 +00:00
delete cfg_desc_[i]->usb_if[j].altsetting;
2022-05-03 08:54:08 +00:00
}
delete[] cfg_desc_[i]->usb_if;
}
delete cfg_desc_[i];
}
cfg_desc_.clear();
is_ok_ = false;
}
int usb_device::get_descriptor(libusb_device_descriptor* desc)
{
2023-04-21 06:29:30 +00:00
if (dev_desc_)
memcpy(desc, dev_desc_, sizeof(*desc));
else
{
char cls[128] = { 0 };
SetupDiGetClassDescriptionA(&guid_, cls, _countof(cls) - 1, NULL);
std::transform(cls, cls + lstrlenA(cls), cls, tolower);
if (strcmp(cls, "usb") == 0)
desc->bDeviceClass = libusb_class_code::LIBUSB_CLASS_HUB;
else if (strcmp(cls, "image") == 0)
desc->bDeviceClass = libusb_class_code::LIBUSB_CLASS_IMAGE;
else if (strcmp(cls, "hidclass") == 0)
desc->bDeviceClass = libusb_class_code::LIBUSB_CLASS_HID;
else
desc->bDeviceClass = libusb_class_code::LIBUSB_CLASS_VENDOR_SPEC;
desc->idVendor = udev_.vid;
desc->idProduct = udev_.pid;
desc->bcdUSB = 0x200; // USB2.0 ?
desc->bcdDevice = 0; // ?
desc->bDescriptorType = libusb_descriptor_type::LIBUSB_DT_DEVICE;
desc->bDeviceProtocol = 0;
desc->bDeviceSubClass = libusb_class_code::LIBUSB_CLASS_IMAGE;
desc->bLength = sizeof(*desc);
desc->bMaxPacketSize0 = 512;
desc->bNumConfigurations = 1; // ?
desc->iManufacturer = 0;
desc->iSerialNumber = 0;
desc->iProduct = 0;
}
return LIBUSB_SUCCESS;
2022-05-03 08:54:08 +00:00
}
int usb_device::get_config_descriptor(int index, libusb_config_descriptor** desc)
{
2023-04-21 06:29:30 +00:00
if (index >= 0 && index < cfg_desc_.size())
*desc = cfg_desc_[index];
else
return LIBUSB_ERROR_INVALID_PARAM;
2022-05-03 08:54:08 +00:00
2023-04-21 06:29:30 +00:00
return LIBUSB_SUCCESS;
2022-05-03 08:54:08 +00:00
}
int usb_device::get_config_string(uint8_t desc_index, unsigned char* data, int length)
{
for (auto& v : str_cfg_)
{
if (v.id == desc_index)
{
if (length < v.val.length())
memcpy(data, v.val.c_str(), length);
else
strcpy((char*)data, v.val.c_str());
return LIBUSB_SUCCESS;
}
}
return LIBUSB_ERROR_NOT_FOUND;
}
2022-05-03 08:54:08 +00:00
int usb_device::open(libusb_device_handle** dev_handle)
{
if (handle_)
return LIBUSB_ERROR_BUSY;
if (!dev_desc_)
init();
2022-08-09 09:07:39 +00:00
2023-04-21 06:29:30 +00:00
HANDLE h = open_usb(udev_.name.c_str());
if (h == INVALID_HANDLE_VALUE)
{
*dev_handle = NULL;
return online_ ? LIBUSB_ERROR_IO : LIBUSB_ERROR_NO_DEVICE;
}
2022-05-03 08:54:08 +00:00
USBSCAN_PIPE_CONFIGURATION upc = { 0 };
DWORD cbr = 0;
std::string fmt("\\%d"), root("");
2022-08-11 10:05:01 +00:00
if (udev_.driver_key.length())
2023-04-21 06:29:30 +00:00
root = usb_device::usb_scan_name(udev_.driver_key.c_str());
2022-08-11 10:05:01 +00:00
if (root.empty())
{
VLOG_MINI_1(LOG_LEVEL_WARNING, "Cannot find '\\\\.\\Usbscan' name for '%s', try run in Administrator!\r\n", udev_.name.c_str());
root = udev_.name;
2022-08-11 10:05:01 +00:00
fmt = "\\%04d";
}
else
{
VLOG_MINI_2(LOG_LEVEL_WARNING, "Nice: '%s' for '%s'.\r\n", root.c_str(), udev_.name.c_str());
2022-08-11 10:05:01 +00:00
}
2022-05-03 08:54:08 +00:00
if (DeviceIoControl(h, IOCTL_GET_PIPE_CONFIGURATION, NULL, 0, &upc, sizeof(upc), &cbr, NULL))
{
2022-08-11 10:05:01 +00:00
int type = PIPE_TYPE::WRITE_DATA_PIPE;
DeviceIoControl(h, IOCTL_RESET_PIPE, &type, sizeof(type), NULL, NULL, &cbr, NULL);
2022-05-03 08:54:08 +00:00
for (int i = 0; i < upc.NumberOfPipes; ++i)
{
USBPIPE up = { 0 };
2022-08-11 10:05:01 +00:00
char ind[80] = { 0 };
2022-05-03 08:54:08 +00:00
up.address = upc.PipeInfo[i].EndpointAddress;
up.type = upc.PipeInfo[i].PipeType;
2022-08-11 10:05:01 +00:00
sprintf_s(ind, _countof(ind) - 1, fmt.c_str(), i);
up.pipe = open_usb((root + ind).c_str());
2022-05-03 08:54:08 +00:00
if (up.pipe != INVALID_HANDLE_VALUE)
{
set_timeout(up.pipe);
2022-08-09 07:08:50 +00:00
up.index = i;
2022-05-03 08:54:08 +00:00
pipes_.push_back(up);
}
}
}
set_timeout(h);
handle_ = h == INVALID_HANDLE_VALUE ? NULL : (libusb_device_handle*)h;
2022-05-03 08:54:08 +00:00
*dev_handle = (libusb_device_handle*)this;
return LIBUSB_SUCCESS;
}
int usb_device::close(void)
{
for (size_t i = 0; i < pipes_.size(); ++i)
{
CancelIo(pipes_[i].pipe);
CloseHandle(pipes_[i].pipe);
}
pipes_.clear();
if (handle_)
{
OVERLAPPED ovl = { 0 };
PIPE_TYPE type = ALL_PIPE;
DWORD cbr = 0;
ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
DeviceIoControl(handle_, IOCTL_CANCEL_IO, &type, sizeof(type), NULL, 0, &cbr, &ovl);
WaitForSingleObject(ovl.hEvent, 1000);
CloseHandle(ovl.hEvent);
CancelIo(handle_);
CloseHandle((HANDLE)handle_);
handle_ = NULL;
}
return LIBUSB_SUCCESS;
}
int usb_device::set_timeout(unsigned milliseconds)
{
timout_ms_ = milliseconds;
for (size_t i = 0; i < pipes_.size(); ++i)
{
set_timeout(pipes_[i].pipe);
}
if (handle_)
set_timeout(handle_);
return LIBUSB_SUCCESS;
}
int usb_device::transfer_bulk(unsigned endpoint, unsigned char* data, int* length, unsigned int timeout)
{
2022-08-09 07:08:50 +00:00
int ret = LIBUSB_ERROR_NOT_SUPPORTED, ind = 0;
HANDLE h = find_pipe(endpoint, USBSCAN_PIPE_BULK, &ind);
2022-05-03 08:54:08 +00:00
if (h)
{
2023-04-21 06:29:30 +00:00
ovl_cls* oc = ovl_mgr_.get_ovl();
2022-05-03 08:54:08 +00:00
DWORD io = 0;
2022-08-11 10:05:01 +00:00
BOOL result = FALSE;
2023-04-21 06:29:30 +00:00
2022-08-11 10:05:01 +00:00
if (endpoint & BULKIN_FLAG)
result = ReadFile(h, data, *length, oc->io_bytes(), oc->over_lapped());
else
{
2023-04-21 06:29:30 +00:00
// oc->over_lapped()->Offset = oc->over_lapped()->OffsetHigh = -1;
2022-08-11 10:05:01 +00:00
result = WriteFile(h, data, *length, oc->io_bytes(), oc->over_lapped());
}
2022-05-03 08:54:08 +00:00
if (result)
{
FlushFileBuffers(h);
*length = *oc->io_bytes();
2022-05-03 08:54:08 +00:00
ret = LIBUSB_SUCCESS;
}
else
{
io = GetLastError();
if (io == ERROR_IO_PENDING)
{
if (WaitForSingleObject(oc->over_lapped()->hEvent, timeout) == WAIT_OBJECT_0)
{
2023-04-21 06:29:30 +00:00
GetOverlappedResult(h, oc->over_lapped(), oc->io_bytes(), FALSE);
2022-08-09 09:07:39 +00:00
*length = *oc->io_bytes();
2022-08-13 08:41:09 +00:00
if (*length == 0 && oc->over_lapped()->Internal != ERROR_SUCCESS)
{
2023-04-21 06:29:30 +00:00
ret = LIBUSB_ERROR_IO;
2022-08-13 08:41:09 +00:00
VLOG_MINI_2(LOG_LEVEL_WARNING, "Bulk-Transfer of endpoint 0x%02x failed with code 0x%08X\n", endpoint, oc->over_lapped()->Internal);
}
else
ret = LIBUSB_SUCCESS;
}
else
ret = LIBUSB_ERROR_TIMEOUT;
2022-05-03 08:54:08 +00:00
}
else
{
if (endpoint & BULKIN_FLAG)
{
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Read-bulk = %d, set error as LIBUSB_ERROR_PIPE\r\n", io);
}
else
{
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Write-bulk = %d, set error as LIBUSB_ERROR_PIPE\r\n", io);
}
ret = LIBUSB_ERROR_PIPE;
}
2022-05-03 08:54:08 +00:00
}
oc->release();
2022-05-03 08:54:08 +00:00
}
return ret;
}
int usb_device::transfer_control(uint8_t type, uint8_t req, uint16_t val, uint16_t ind, unsigned char* data, uint16_t len, unsigned timeout)
{
// return transfer bytes ...
int ret = 0; // LIBUSB_ERROR_NOT_FOUND;
2022-05-03 08:54:08 +00:00
_IO_BLOCK_EX irp;
if ((HANDLE)handle_ != INVALID_HANDLE_VALUE)
{
DWORD io = 0;
2023-04-21 06:29:30 +00:00
ovl_cls* oc = ovl_mgr_.get_ovl();
2022-05-03 08:54:08 +00:00
irp.bmRequestType = (type >> 5) & 0x03;
irp.bRequest = req;
irp.fTransferDirectionIn = type >> 7;
irp.pbyData = data;
irp.uIndex = ind;
irp.uLength = len;
irp.uOffset = val;
if (DeviceIoControl((HANDLE)handle_, IOCTL_SEND_USB_REQUEST, &irp, sizeof(irp), data, len, oc->io_bytes(), oc->over_lapped()))
2022-07-21 09:55:25 +00:00
{
if (irp.fTransferDirectionIn)
{
2023-04-21 06:29:30 +00:00
GetOverlappedResult((HANDLE)handle_, oc->over_lapped(), oc->io_bytes(), FALSE);
2022-07-21 09:55:25 +00:00
ret = *oc->io_bytes();
}
else
{
ret = len;
}
}
2022-05-03 08:54:08 +00:00
else if (GetLastError() == ERROR_IO_PENDING)
{
ret = WaitForSingleObject(oc->over_lapped()->hEvent, timeout) == WAIT_TIMEOUT ? 0 : *oc->io_bytes();
2022-05-03 08:54:08 +00:00
}
else
2022-07-21 09:55:25 +00:00
{
io = GetLastError();
if (io == ERROR_ACCESS_DENIED)
ret = LIBUSB_ERROR_ACCESS;
else if (io == ERROR_SEM_TIMEOUT)
ret = LIBUSB_ERROR_TIMEOUT;
else
ret = LIBUSB_ERROR_PIPE;
// ret = 0;
2022-07-21 09:55:25 +00:00
}
oc->release();
2022-05-03 08:54:08 +00:00
}
return ret;
}
int usb_device::transfer_interrupt(unsigned endpoint, unsigned char* data, int* length, unsigned int timeout)
{
int ret = LIBUSB_ERROR_NOT_SUPPORTED, len = *length;
2022-05-03 08:54:08 +00:00
HANDLE h = find_pipe(endpoint, USBSCAN_PIPE_INTERRUPT);
DWORD io = 0;
2023-04-21 06:29:30 +00:00
*length = 0;
2022-05-03 08:54:08 +00:00
if (h)
{
2023-04-21 06:29:30 +00:00
ovl_cls* oc = ovl_mgr_.get_ovl();
if (DeviceIoControl(h, IOCTL_WAIT_ON_DEVICE_EVENT, NULL, 0, data, len, oc->io_bytes(), oc->over_lapped()))
2022-05-03 08:54:08 +00:00
{
ret = LIBUSB_SUCCESS;
*length = *oc->io_bytes();
2022-05-03 08:54:08 +00:00
}
else
{
io = GetLastError();
if (io == ERROR_IO_PENDING)
{
if (WaitForSingleObject(oc->over_lapped()->hEvent, timeout) == WAIT_OBJECT_0)
{
2023-04-21 06:29:30 +00:00
GetOverlappedResult(h, oc->over_lapped(), oc->io_bytes(), FALSE);
*length = *oc->io_bytes();
ret = LIBUSB_SUCCESS;
}
else
{
ret = LIBUSB_ERROR_TIMEOUT;
// 此错误可能导致后续新产生的数据被填充进data故取消该操作 BUG-242
CancelIo(h);
}
2022-05-03 08:54:08 +00:00
}
else
{
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "DeviceIoControl(INT-EP) = %d, set error as LIBUSB_ERROR_PIPE\r\n", io);
ret = LIBUSB_ERROR_PIPE;
}
2022-05-03 08:54:08 +00:00
}
oc->release();
2022-05-03 08:54:08 +00:00
}
return ret;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// usb_monitor ...
usb_monitor* usb_monitor::usb_monitor_ = NULL;
UINT usb_monitor::find_usb_timer_ = 101;
2022-05-03 08:54:08 +00:00
usb_monitor::usb_monitor() : wnd_monitor_(NULL), handle_msg_id_(0), run_(true)
{
handle_msg_.reset(new std::thread(&usb_monitor::thread_handle_device_change_msg, this));
}
usb_monitor::~usb_monitor()
{
quit();
}
int usb_monitor::enum_usb_device(bool(__stdcall* found_usb)(LPUSBDEV dev, void* param), void* param, bool hub)
{
GUID hid = hub ? GUID_DEVINTERFACE_USB_HUB : GUID_DEVINTERFACE_USB_DEVICE;
HDEVINFO dev_info = NULL;
int ind = 0;
SP_DEVICE_INTERFACE_DATA id = { 0 };
SP_DEVINFO_DATA sdd = { 0 };
dev_info = SetupDiGetClassDevsW(&hid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (!dev_info)
return GetLastError();
id.cbSize = sizeof(id);
while (SetupDiEnumDeviceInterfaces(dev_info, NULL, &hid, ind++, &id))
{
PSP_DEVICE_INTERFACE_DETAIL_DATA_W buf = NULL;
DWORD size = 0;
SetupDiGetDeviceInterfaceDetailW(dev_info, &id, buf, 0, &size, NULL);
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
buf = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)new wchar_t[size + 4];
memset(buf, 0, (size + 4) * 2);
buf->cbSize = sizeof(*buf);
if (SetupDiGetDeviceInterfaceDetailW(dev_info, &id, buf, buf->cbSize + size, NULL, NULL))
{
USBDEV dev;
DWORD len = size;
dev.name = u2utf8(buf->DevicePath);
usb_device::vid_pid_from_name(dev.name.c_str(), &dev.vid, &dev.pid);
sdd.cbSize = sizeof(sdd);
SetupDiEnumDeviceInfo(dev_info, ind - 1, &sdd);
if (SetupDiGetDeviceRegistryPropertyW(dev_info, &sdd, SPDRP_DRIVER, NULL, (PBYTE)buf->DevicePath, len, &len)) // driver key
dev.driver_key = u2utf8(buf->DevicePath);
len = size;
2023-04-21 06:29:30 +00:00
if (SetupDiGetDeviceRegistryPropertyW(dev_info, &sdd, SPDRP_DEVICEDESC, NULL, (PBYTE)buf->DevicePath, len, &len)) // device description
dev.desc = u2utf8(buf->DevicePath);
len = size;
if (SetupDiGetDeviceRegistryPropertyW(dev_info, &sdd, SPDRP_ADDRESS, NULL, (PBYTE)buf->DevicePath, len, &len)) // device description
dev.port = *(int*)buf->DevicePath;
if (!found_usb(&dev, param))
{
delete[](char*)buf;
break;
}
}
delete[](char*)buf;
}
id.cbSize = sizeof(id);
}
SetupDiDestroyDeviceInfoList(dev_info);
return ERROR_SUCCESS;
}
bool __stdcall usb_monitor::find_all_usb_devices(LPUSBDEV dev, void* param/*std::vector<USBDEV>* */)
{
std::vector<USBDEV>* devs = (std::vector<USBDEV>*)param;
devs->push_back(*dev);
return true;
}
bool __stdcall usb_monitor::usb_dev_by_name(LPUSBDEV dev, void* param/*LPUSBDEV*/)
{
LPUSBDEV devt = (LPUSBDEV)param;
if (stricmp(usb_device::name_without_guid(devt->name.c_str()).c_str(), usb_device::name_without_guid(dev->name.c_str()).c_str()) == 0)
{
devt->driver_key = dev->driver_key;
devt->desc = dev->desc;
devt->vid = dev->vid;
devt->pid = dev->pid;
devt->port = dev->port;
return false;
}
return true;
}
bool __stdcall usb_monitor::find_parent_hub(LPUSBDEV hub, void* param/*LPUSBDEV*/)
{
LPUSBDEV t = (LPUSBDEV)param;
if (t->driver_key.empty() || t->port == 0)
return false;
HANDLE h = CreateFileA(hub->name.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
bool go = true;
char buf[512] = { 0 };
DWORD bytes = 0;
if (h == INVALID_HANDLE_VALUE)
return true;
USB_NODE_CONNECTION_DRIVERKEY_NAME* name = (USB_NODE_CONNECTION_DRIVERKEY_NAME*)buf;
name->ConnectionIndex = t->port;
name->ActualLength = (sizeof(buf) - sizeof(*name)) / 2 - 1;
if (DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, name, sizeof(*name), name, name->ActualLength, &bytes, NULL))
{
if (u2utf8(name->DriverKeyName) == t->driver_key)
{
t->hub = hub->name;
go = false;
}
}
CloseHandle(h);
return go;
}
bool usb_monitor::is_desired_usb_device(int vid, int pid)
{
2023-01-10 02:30:22 +00:00
return true; // vid == PRODUCT_VID || vid == PRODUCT_VENDOR_HG1;
}
2022-05-03 08:54:08 +00:00
LRESULT CALLBACK usb_monitor::monitor_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
usb_monitor* monitor = (usb_monitor*)GetPropW(hwnd, MONITOR_WINDOW_OWNER);
if (msg == WM_CREATE)
{
LPCREATESTRUCTW data = (LPCREATESTRUCTW)lp;
SetPropW(hwnd, MONITOR_WINDOW_OWNER, (HANDLE)data->lpCreateParams);
return 0;
}
else if (monitor && msg == WM_TIMER && wp == usb_monitor::find_usb_timer_)
{
monitor->find_usb_and_trigger_event();
return 0;
}
2022-05-03 08:54:08 +00:00
else if (!monitor || msg != WM_DEVICECHANGE)
return DefWindowProcW(hwnd, msg, wp, lp);
return monitor->on_usb_pnp(wp, lp);
}
void usb_monitor::register_monitor_wnd(const wchar_t* cls)
{
WNDCLASSW wc = { 0 };
wc.lpfnWndProc = &usb_monitor::monitor_wnd_proc;
wc.lpszClassName = cls;
wc.hInstance = GetModuleHandleW(NULL);
RegisterClassW(&wc);
}
void usb_monitor::notify_usb_event(usb_device*& dev, bool arrive)
{
std::lock_guard<std::mutex> lock(lock_);
2022-08-06 12:43:40 +00:00
int ev = arrive ? LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED : LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT;
std::string noguid(usb_device::name_without_guid(dev->name().c_str()));
2022-05-03 08:54:08 +00:00
if (arrive)
{
bool found = false;
2023-04-21 06:29:30 +00:00
for (size_t i = 0; i < devices_.size(); ++i)
2022-05-03 08:54:08 +00:00
{
// if (devices_[i]->name() == dev->name())
if (stricmp(usb_device::name_without_guid(devices_[i]->name().c_str()).c_str(), noguid.c_str()) == 0)
2022-05-03 08:54:08 +00:00
{
2022-08-06 12:43:40 +00:00
if (devices_[i]->is_online())
{
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "%s is already in device queue and received ARRIVE again, discard this event.\n", dev->name().c_str());
2023-04-21 06:29:30 +00:00
// dev->release();
2022-08-06 12:43:40 +00:00
return;
}
else
{
devices_[i]->clear();
devices_[i]->dev() = dev->dev(); // use NEW connection info ...
2022-08-09 07:08:50 +00:00
dev->release();
2022-08-06 12:43:40 +00:00
dev = devices_[i];
dev->add_ref();
dev->set_online(true);
found = true;
break;
}
2022-05-03 08:54:08 +00:00
}
}
if (!found)
{
devices_.push_back(dev);
dev->add_ref();
}
}
else
{
2022-10-19 06:00:23 +00:00
bool discard = false;
2022-05-03 08:54:08 +00:00
for (size_t i = 0; i < devices_.size(); ++i)
{
// if (devices_[i]->name() == dev->name())
if (stricmp(usb_device::name_without_guid(devices_[i]->name().c_str()).c_str(), noguid.c_str()) == 0)
2022-05-03 08:54:08 +00:00
{
2022-10-19 06:00:23 +00:00
dev->release();
dev = devices_[i];
dev->add_ref();
if (dev->is_online())
2022-08-06 12:43:40 +00:00
{
dev->set_online(false);
discard = false;
2022-08-06 12:43:40 +00:00
}
else
{
discard = true;
}
break;
2022-05-03 08:54:08 +00:00
}
2022-10-19 06:00:23 +00:00
}
if (discard)
{
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "%s is already offline and received LEAVE again, discard this event.\n", dev->name().c_str());
return;
2022-05-03 08:54:08 +00:00
}
}
for (size_t i = 0; i < cbs_.size(); ++i)
cbs_[i]->notify((libusb_context*)this, dev, ev);
}
int usb_monitor::on_usb_pnp(WPARAM wp, LPARAM lp)
{
int ret = 0;
DEV_BROADCAST_HDR* dbt = (DEV_BROADCAST_HDR*)lp;
if (!dbt || dbt->dbch_devicetype != DBT_DEVTYP_DEVICEINTERFACE)
return wp == DBT_DEVICEQUERYREMOVE;
PDEV_BROADCAST_DEVICEINTERFACE_W dev = (PDEV_BROADCAST_DEVICEINTERFACE_W)lp;
2023-04-21 06:29:30 +00:00
if (dev->dbcc_classguid == GUID_DEVINTERFACE_USB_DEVICE)
{
return wp == DBT_DEVICEQUERYREMOVE;
}
2022-05-03 08:54:08 +00:00
std::string utf8(u2utf8(dev->dbcc_name));
2023-04-21 06:29:30 +00:00
if (wp == DBT_DEVICEQUERYREMOVE)
return cur_dev_name_ != utf8;
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "event '%08x' of device %s\n", wp, utf8.c_str());
2022-05-03 08:54:08 +00:00
int vid = 0,
pid = 0;
usb_device::vid_pid_from_name(utf8.c_str(), &vid, &pid);
if (!usb_monitor::is_desired_usb_device(vid, pid))
return 0;
2022-08-06 12:43:40 +00:00
USBDEV udev;
udev.name = utf8;
usb_monitor::enum_usb_device(&usb_monitor::usb_dev_by_name, &udev);
if (wp == DBT_DEVICEARRIVAL && udev.driver_key.empty())
{
VLOG_MINI_1(LOG_LEVEL_FATAL, "Failed: driver key for '%s' is not found!\r\n", utf8.c_str());
}
usb_device* ud = new usb_device(udev);
2022-05-03 08:54:08 +00:00
*ud = dev->dbcc_classguid;
2023-04-21 06:29:30 +00:00
if (!PostThreadMessageW(handle_msg_id_, MSG_DEVICE_PNP, wp == DBT_DEVICEARRIVAL, (LPARAM)ud))
2022-05-03 08:54:08 +00:00
ud->release();
return ret;
}
void usb_monitor::find_usb_and_trigger_event(void)
2022-05-03 08:54:08 +00:00
{
std::vector<USBDEV> old(found_usb_devs_);
2022-05-03 08:54:08 +00:00
found_usb_devs_.clear();
usb_monitor::enum_usb_device(&usb_monitor::find_all_usb_devices, &found_usb_devs_);
for (size_t i = 0; i < found_usb_devs_.size(); ++i)
2022-05-03 08:54:08 +00:00
{
if (!usb_monitor::is_desired_usb_device(found_usb_devs_[i].vid, found_usb_devs_[i].pid))
2022-05-03 08:54:08 +00:00
{
found_usb_devs_.erase(found_usb_devs_.begin() + i);
i--;
2022-05-03 08:54:08 +00:00
}
}
for (size_t i = 0; i < found_usb_devs_.size(); ++i)
{
std::vector<USBDEV>::iterator it = std::find(old.begin(), old.end(), found_usb_devs_[i]);
if (it == old.end())
{
usb_device* dev = new usb_device(found_usb_devs_[i]);
notify_usb_event(dev, true);
dev->release();
}
else
old.erase(it);
}
for (size_t i = 0; i < old.size(); ++i)
{
usb_device* dev = new usb_device(old[i]);
notify_usb_event(dev, false);
dev->release();
}
}
2022-05-03 08:54:08 +00:00
usb_callback* usb_monitor::reg_callback(libusb_hotplug_callback_fn cb, void* param)
{
usb_callback* obj = new usb_callback(cb, param);
{
std::lock_guard<std::mutex> lock(lock_);
cbs_.push_back(obj);
}
return obj;
}
void usb_monitor::unreg_callback(usb_callback* cb)
{
std::lock_guard<std::mutex> lock(lock_);
for (int i = 0; i < cbs_.size(); ++i)
{
if (cbs_[i] == cb)
{
cbs_.erase(cbs_.begin() + i);
delete cb;
break;
}
}
}
void usb_monitor::thread_run_device_event_wnd(void)
{
MSG msg = { 0 };
const wchar_t* cls = L"usb_pnp_wnd";
register_monitor_wnd(cls);
wnd_monitor_ = CreateWindowW(cls, L"usb", WS_POPUP, 0, 0, 0, 0, NULL, NULL, GetModuleHandleW(NULL), this);
if (!IsWindow(wnd_monitor_))
{
2023-04-21 06:29:30 +00:00
if (run_)
2022-05-03 08:54:08 +00:00
Sleep(1000);
return;
}
if (run_)
{
BOOL ret = TRUE;
DEV_BROADCAST_HDR dbh = { 0 };
HDEVNOTIFY notify = NULL;
// mannual triggered at beginning ...
find_usb_and_trigger_event();
2022-05-03 08:54:08 +00:00
dbh.dbch_size = sizeof(dbh);
dbh.dbch_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
notify = RegisterDeviceNotificationW(wnd_monitor_, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
if (!notify && GetLastError() == ERROR_SERVICE_SPECIFIC_ERROR)
{
DEV_BROADCAST_DEVICEINTERFACE_A di = { 0 };
di.dbcc_size = (sizeof(di) + 3) / 4 * 4;
di.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
UuidFromStringA((RPC_CSTR)IMAGE_CLASS_GUID, &di.dbcc_classguid);
notify = RegisterDeviceNotificationA(wnd_monitor_, &di, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "RegisterDeviceNotificationA = 0x%08x, error = %d. di.dbcc_size = %d\n", notify, GetLastError(), di.dbcc_size);
if (!notify)
SetTimer(wnd_monitor_, usb_monitor::find_usb_timer_, 1000, NULL);
}
2022-05-03 08:54:08 +00:00
ret = GetLastError();
while (run_ && (ret = GetMessageW(&msg, wnd_monitor_, 0, 0)))
{
if (ret == -1)
break;
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
UnregisterDeviceNotification(notify);
}
DestroyWindow(wnd_monitor_);
UnregisterClassW(cls, GetModuleHandleW(NULL));
}
void usb_monitor::thread_handle_device_change_msg(void)
{
MSG msg = { 0 };
BOOL ret = FALSE;
handle_msg_id_ = GetCurrentThreadId();
while ((ret = GetMessageW(&msg, NULL, 0, 0)))
{
if (ret == -1)
break;
if (msg.message == MSG_DEVICE_PNP)
{
char buf[40] = { 0 };
usb_device* dev = (usb_device*)msg.lParam;
//if(msg.wParam)
// dev->init();
notify_usb_event(dev, msg.wParam);
// dev->release ?
dev->release();
}
else
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
}
void usb_monitor::quit(void)
{
KillTimer(wnd_monitor_, usb_monitor::find_usb_timer_);
2022-05-03 08:54:08 +00:00
run_ = false;
if (IsWindow(wnd_monitor_))
{
PostMessage(wnd_monitor_, WM_QUIT, 0, 0);
Sleep(100);
}
2022-05-03 08:54:08 +00:00
if (handle_msg_.get())
{
PostThreadMessageW(handle_msg_id_, WM_QUIT, 0, 0);
if (handle_msg_->joinable())
handle_msg_->join();
handle_msg_.reset();
}
{
std::lock_guard<std::mutex> lock(lock_);
for (auto& v : devices_)
v->release();
devices_.clear();
}
2022-05-03 08:54:08 +00:00
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// libusb APIs ...
int LIBUSB_CALL libusb_init(libusb_context** ctx)
{
if (ctx)
*ctx = (libusb_context*)new usb_monitor();
2023-04-21 06:29:30 +00:00
else if (!usb_monitor::usb_monitor_)
2022-05-03 08:54:08 +00:00
usb_monitor::usb_monitor_ = new usb_monitor();
return LIBUSB_SUCCESS;
}
void LIBUSB_CALL libusb_exit(libusb_context* ctx)
{
usb_monitor* usb = (usb_monitor*)ctx;
if (usb)
{
usb->quit();
delete usb;
}
}
int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context* ctx,
libusb_hotplug_event events,
libusb_hotplug_flag flags,
int vendor_id, int product_id,
int dev_class,
libusb_hotplug_callback_fn cb_fn,
void* user_data,
libusb_hotplug_callback_handle* callback_handle)
{
if (ctx)
*callback_handle = (libusb_hotplug_callback_handle)((usb_monitor*)ctx)->reg_callback(cb_fn, user_data);
else if (usb_monitor::usb_monitor_)
*callback_handle = (libusb_hotplug_callback_handle)usb_monitor::usb_monitor_->reg_callback(cb_fn, user_data);
return LIBUSB_SUCCESS;
}
void LIBUSB_CALL libusb_hotplug_deregister_callback(libusb_context* ctx, libusb_hotplug_callback_handle callback_handle)
{
if (ctx)
((usb_monitor*)ctx)->unreg_callback((usb_callback*)callback_handle);
else if (usb_monitor::usb_monitor_)
2023-04-21 06:29:30 +00:00
usb_monitor::usb_monitor_->unreg_callback((usb_callback*)callback_handle);
2022-05-03 08:54:08 +00:00
}
int LIBUSB_CALL libusb_handle_events_timeout(libusb_context* ctx, struct timeval* tv)
{
// NOTE: for the caller is in a separate thread, this call will blocked while process exited, or libusb_exit called
((usb_monitor*)ctx)->thread_run_device_event_wnd();
return LIBUSB_SUCCESS;
}
libusb_device* LIBUSB_CALL libusb_ref_device(libusb_device* dev)
{
if (dev)
((usb_device*)dev)->add_ref();
return dev;
}
void LIBUSB_CALL libusb_unref_device(libusb_device* dev)
{
if (dev)
((usb_device*)dev)->release();
}
int LIBUSB_CALL libusb_get_device_descriptor(libusb_device* dev, struct libusb_device_descriptor* desc)
{
2023-04-21 06:29:30 +00:00
if (!dev)
return LIBUSB_ERROR_INVALID_PARAM;
2022-05-03 08:54:08 +00:00
2023-04-21 06:29:30 +00:00
return ((usb_device*)dev)->get_descriptor(desc);
2022-05-03 08:54:08 +00:00
}
int LIBUSB_CALL libusb_get_config_descriptor(libusb_device* dev, uint8_t config_index, struct libusb_config_descriptor** config)
{
2023-04-21 06:29:30 +00:00
if (!dev)
return LIBUSB_ERROR_INVALID_PARAM;
2022-05-03 08:54:08 +00:00
2023-04-21 06:29:30 +00:00
return ((usb_device*)dev)->get_config_descriptor(config_index, config);
2022-05-03 08:54:08 +00:00
}
void LIBUSB_CALL libusb_free_config_descriptor(struct libusb_config_descriptor* config)
{
2023-04-21 06:29:30 +00:00
// because the configuration descriptor is member of device, nothing to do here ...
2022-05-03 08:54:08 +00:00
}
int LIBUSB_CALL libusb_reset_device(libusb_device_handle* dev_handle)
{
// to be implemented later ...
return LIBUSB_SUCCESS;
}
ssize_t LIBUSB_CALL libusb_get_device_list(libusb_context* ctx, libusb_device*** list)
{
// to be implemented later ...
return 0;
}
void LIBUSB_CALL libusb_free_device_list(libusb_device** list, int unref_devices)
{
// to be implemented later ...
}
int LIBUSB_CALL libusb_set_auto_detach_kernel_driver(libusb_device_handle* dev_handle, int enable)
{
// to be implemented later ...
return LIBUSB_SUCCESS;
}
int LIBUSB_CALL libusb_claim_interface(libusb_device_handle* dev_handle, int interface_number)
{
// to be implemented later ...
return LIBUSB_SUCCESS;
}
int LIBUSB_CALL libusb_release_interface(libusb_device_handle* dev_handle, int interface_number)
{
// to be implemented later ...
return LIBUSB_SUCCESS;
}
int LIBUSB_CALL libusb_set_configuration(libusb_device_handle* dev_handle, int configuration)
{
// to be implemented later ...
return LIBUSB_SUCCESS;
}
int LIBUSB_CALL libusb_kernel_driver_active(libusb_device_handle* dev_handle, int interface_number)
{
// to be implemented later ...
return LIBUSB_SUCCESS;
}
int LIBUSB_CALL libusb_detach_kernel_driver(libusb_device_handle* dev_handle, int interface_number)
{
// to be implemented later ...
return LIBUSB_SUCCESS;
}
int LIBUSB_CALL libusb_attach_kernel_driver(libusb_device_handle* dev_handle, int interface_number)
{
// to be implemented later ...
return LIBUSB_SUCCESS;
}
libusb_device_handle* LIBUSB_CALL libusb_open_device_with_vid_pid(libusb_context* ctx, uint16_t vendor_id, uint16_t product_id)
{
// to be implemented later ...
return NULL;
}
int LIBUSB_CALL libusb_clear_halt(libusb_device_handle* dev_handle, unsigned char endpoint)
{
// to be implemented later ...
return LIBUSB_SUCCESS;
}
const char* LIBUSB_CALL libusb_error_name(int errcode)
{
#define RETURN_IF(e) \
if(errcode == e) \
return #e;
RETURN_IF(LIBUSB_SUCCESS);
RETURN_IF(LIBUSB_ERROR_IO);
RETURN_IF(LIBUSB_ERROR_INVALID_PARAM);
RETURN_IF(LIBUSB_ERROR_ACCESS);
RETURN_IF(LIBUSB_ERROR_NO_DEVICE);
RETURN_IF(LIBUSB_ERROR_NOT_FOUND);
RETURN_IF(LIBUSB_ERROR_BUSY);
RETURN_IF(LIBUSB_ERROR_TIMEOUT);
RETURN_IF(LIBUSB_ERROR_OVERFLOW);
RETURN_IF(LIBUSB_ERROR_PIPE);
RETURN_IF(LIBUSB_ERROR_INTERRUPTED);
RETURN_IF(LIBUSB_ERROR_NO_MEM);
RETURN_IF(LIBUSB_ERROR_NOT_SUPPORTED);
RETURN_IF(LIBUSB_ERROR_OTHER);
return "Unknown error";
}
int LIBUSB_CALL libusb_open(libusb_device* dev, libusb_device_handle** dev_handle)
{
if (!dev)
return LIBUSB_ERROR_INVALID_PARAM;
return ((usb_device*)dev)->open(dev_handle);
}
void LIBUSB_CALL libusb_close(libusb_device_handle* dev_handle)
{
if (dev_handle)
{
((usb_device*)dev_handle)->close();
}
}
int LIBUSB_CALL libusb_control_transfer(libusb_device_handle* dev_handle,
uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
unsigned char* data, uint16_t wLength, unsigned int timeout)
{
if (!dev_handle)
return LIBUSB_ERROR_INVALID_PARAM;
return ((usb_device*)dev_handle)->transfer_control(request_type, bRequest, wValue, wIndex, data, wLength, timeout);
}
int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle* dev_handle,
unsigned char endpoint, unsigned char* data, int length,
int* actual_length, unsigned int timeout)
{
if (!dev_handle)
return LIBUSB_ERROR_INVALID_PARAM;
if (actual_length)
*actual_length = length;
else
actual_length = &length;
return ((usb_device*)dev_handle)->transfer_bulk(endpoint, data, actual_length, timeout);
}
int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle* dev_handle,
unsigned char endpoint, unsigned char* data, int length,
int* actual_length, unsigned int timeout)
{
if (!dev_handle)
return LIBUSB_ERROR_INVALID_PARAM;
if (actual_length)
*actual_length = length;
else
actual_length = &length;
return ((usb_device*)dev_handle)->transfer_interrupt(endpoint, data, actual_length, timeout);
}
int LIBUSB_CALL libusb_set_timeout(libusb_device_handle* h, unsigned int milliseconds)
{
if (!h)
return LIBUSB_ERROR_INVALID_PARAM;
return ((usb_device*)h)->set_timeout(milliseconds);
}
void LIBUSB_CALL libusb_quit(libusb_context* ctx)
{
if (ctx)
((usb_monitor*)ctx)->quit();
}
uint8_t LIBUSB_CALL libusb_get_device_address(libusb_device* device)
{
2023-04-21 06:29:30 +00:00
if (!device)
2022-05-03 08:54:08 +00:00
return 0;
return ((usb_device*)device)->address();
2022-05-03 08:54:08 +00:00
}
int LIBUSB_CALL libusb_get_string_descriptor_ascii(libusb_device_handle* dev_handle,
uint8_t desc_index, unsigned char* data, int length)
{
return ((usb_device*)dev_handle)->get_config_string(desc_index, data, length);
}
2023-04-21 06:29:30 +00:00