回退 win_usb.cpp

This commit is contained in:
13038267101 2023-04-21 14:29:30 +08:00
parent 63acafc433
commit f0b05abd2e
2 changed files with 125 additions and 163 deletions

View File

@ -10,7 +10,6 @@
//#include <winioctl.h> //#include <winioctl.h>
#include <usbscan.h> #include <usbscan.h>
#include <Dbt.h> #include <Dbt.h>
#include <ntstatus.h> // for STATUS_CANCELLED - 0xC0000120
#pragma comment(lib, "setupapi.lib") #pragma comment(lib, "setupapi.lib")
#pragma comment(lib, "hid.lib") #pragma comment(lib, "hid.lib")
@ -52,7 +51,7 @@ std::string u2utf8(const wchar_t* u)
return hg_log::u2utf8(u); return hg_log::u2utf8(u);
#else #else
int len = WideCharToMultiByte(CP_UTF8, 0, u, lstrlenW(u), NULL, 0, NULL, NULL); int len = WideCharToMultiByte(CP_UTF8, 0, u, lstrlenW(u), NULL, 0, NULL, NULL);
char *ansi = new char[len + 4]; char* ansi = new char[len + 4];
len = WideCharToMultiByte(CP_UTF8, 0, u, lstrlenW(u), ansi, len, NULL, NULL); len = WideCharToMultiByte(CP_UTF8, 0, u, lstrlenW(u), ansi, len, NULL, NULL);
ansi[len--] = 0; ansi[len--] = 0;
@ -79,7 +78,7 @@ std::wstring ansi2unicode(const char* ansi, UINT cp = CP_ACP)
} }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// OVERLAPPED ... // OVERLAPPED ...
ovl_cls::ovl_cls(uint32_t type) : ref_(1), io_bytes_(0), type_(type) ovl_cls::ovl_cls() : ref_(1), io_bytes_(0)
{ {
memset(&ovl_, 0, sizeof(ovl_)); memset(&ovl_, 0, sizeof(ovl_));
ovl_.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); ovl_.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
@ -110,14 +109,6 @@ bool ovl_cls::is_waited(void)
{ {
return WaitForSingleObject(ovl_.hEvent, 0) == WAIT_OBJECT_0; return WaitForSingleObject(ovl_.hEvent, 0) == WAIT_OBJECT_0;
} }
void ovl_cls::notify(void)
{
SetEvent(ovl_.hEvent);
}
uint32_t ovl_cls::type(void)
{
return type_;
}
ovl_mgr::ovl_mgr() ovl_mgr::ovl_mgr()
{} {}
@ -127,14 +118,14 @@ ovl_mgr::~ovl_mgr()
v->release(); v->release();
} }
ovl_cls* ovl_mgr::get_ovl(uint32_t type) ovl_cls* ovl_mgr::get_ovl(void)
{ {
std::lock_guard<std::mutex> lock(lock_); std::lock_guard<std::mutex> lock(lock_);
ovl_cls* o = NULL; ovl_cls* o = NULL;
for (auto& v : ovls_) for (auto& v : ovls_)
{ {
if (v->is_waited() && v->type() == type) if (v->is_waited())
{ {
o = v; o = v;
o->add_ref(); o->add_ref();
@ -145,23 +136,18 @@ ovl_cls* ovl_mgr::get_ovl(uint32_t type)
if (!o) if (!o)
{ {
o = new ovl_cls(type); o = new ovl_cls();
ovls_.push_back(o); ovls_.push_back(o);
o->add_ref(); o->add_ref();
} }
return o; return o;
} }
void ovl_mgr::notify_all(void)
{
for (auto& v : ovls_)
v->notify();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// usb_device ... // usb_device ...
usb_device::usb_device(const USBDEV& dev) : ref_(1), udev_(dev), is_ok_(false) usb_device::usb_device(const USBDEV& dev) : ref_(1), udev_(dev), is_ok_(false)
, dev_desc_(NULL), handle_(NULL), online_(true), timout_ms_(1000) , dev_desc_(NULL), handle_(NULL), online_(true), timout_ms_(1000)
{ {
memset(&guid_, 0, sizeof(guid_)); memset(&guid_, 0, sizeof(guid_));
} }
@ -545,14 +531,20 @@ int usb_device::open(libusb_device_handle** dev_handle)
if (!dev_desc_) if (!dev_desc_)
init(); init();
HANDLE h = INVALID_HANDLE_VALUE; 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;
}
USBSCAN_PIPE_CONFIGURATION upc = { 0 }; USBSCAN_PIPE_CONFIGURATION upc = { 0 };
DWORD cbr = 0; DWORD cbr = 0;
std::string fmt("\\%d"), root(""); std::string fmt("\\%d"), root("");
if (udev_.driver_key.length()) if (udev_.driver_key.length())
root = usb_device::usb_scan_name(udev_.driver_key.c_str());//name使用root时会导致 IO一个异常 root = usb_device::usb_scan_name(udev_.driver_key.c_str());
if (root.empty()) 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()); VLOG_MINI_1(LOG_LEVEL_WARNING, "Cannot find '\\\\.\\Usbscan' name for '%s', try run in Administrator!\r\n", udev_.name.c_str());
@ -563,13 +555,6 @@ int usb_device::open(libusb_device_handle** dev_handle)
{ {
VLOG_MINI_2(LOG_LEVEL_WARNING, "Nice: '%s' for '%s'.\r\n", root.c_str(), udev_.name.c_str()); VLOG_MINI_2(LOG_LEVEL_WARNING, "Nice: '%s' for '%s'.\r\n", root.c_str(), udev_.name.c_str());
} }
h = open_usb(udev_.name.c_str());
if (h == INVALID_HANDLE_VALUE)
{
*dev_handle = NULL;
return online_ ? LIBUSB_ERROR_IO : LIBUSB_ERROR_NO_DEVICE;
}
if (DeviceIoControl(h, IOCTL_GET_PIPE_CONFIGURATION, NULL, 0, &upc, sizeof(upc), &cbr, NULL)) if (DeviceIoControl(h, IOCTL_GET_PIPE_CONFIGURATION, NULL, 0, &upc, sizeof(upc), &cbr, NULL))
{ {
int type = PIPE_TYPE::WRITE_DATA_PIPE; int type = PIPE_TYPE::WRITE_DATA_PIPE;
@ -603,7 +588,6 @@ int usb_device::close(void)
CancelIo(pipes_[i].pipe); CancelIo(pipes_[i].pipe);
CloseHandle(pipes_[i].pipe); CloseHandle(pipes_[i].pipe);
} }
ovl_mgr_.notify_all();
pipes_.clear(); pipes_.clear();
if (handle_) if (handle_)
@ -643,7 +627,7 @@ int usb_device::transfer_bulk(unsigned endpoint, unsigned char* data, int* lengt
if (h) if (h)
{ {
ovl_cls* oc = ovl_mgr_.get_ovl(endpoint); ovl_cls* oc = ovl_mgr_.get_ovl();
DWORD io = 0; DWORD io = 0;
BOOL result = FALSE; BOOL result = FALSE;
@ -668,13 +652,11 @@ int usb_device::transfer_bulk(unsigned endpoint, unsigned char* data, int* lengt
{ {
if (WaitForSingleObject(oc->over_lapped()->hEvent, timeout) == WAIT_OBJECT_0) if (WaitForSingleObject(oc->over_lapped()->hEvent, timeout) == WAIT_OBJECT_0)
{ {
GetOverlappedResult(h, oc->over_lapped(), oc->io_bytes(), TRUE); GetOverlappedResult(h, oc->over_lapped(), oc->io_bytes(), FALSE);
*length = *oc->io_bytes(); *length = *oc->io_bytes();
if (*length == 0 && oc->over_lapped()->Internal != ERROR_SUCCESS) if (*length == 0 && oc->over_lapped()->Internal != ERROR_SUCCESS)
{ {
ret = oc->over_lapped()->Internal == STATUS_CANCELLED ? /*LIBUSB_ERROR_TRY_AGAIN*/LIBUSB_ERROR_INTERRUPTED : oc->over_lapped()->Internal; ret = LIBUSB_ERROR_IO;
if (ret == ERROR_NO_MORE_ITEMS)
ret = LIBUSB_ERROR_TIMEOUT;
VLOG_MINI_2(LOG_LEVEL_WARNING, "Bulk-Transfer of endpoint 0x%02x failed with code 0x%08X\n", endpoint, oc->over_lapped()->Internal); VLOG_MINI_2(LOG_LEVEL_WARNING, "Bulk-Transfer of endpoint 0x%02x failed with code 0x%08X\n", endpoint, oc->over_lapped()->Internal);
} }
else else
@ -710,7 +692,7 @@ int usb_device::transfer_control(uint8_t type, uint8_t req, uint16_t val, uint16
if ((HANDLE)handle_ != INVALID_HANDLE_VALUE) if ((HANDLE)handle_ != INVALID_HANDLE_VALUE)
{ {
DWORD io = 0; DWORD io = 0;
ovl_cls *oc = ovl_mgr_.get_ovl(0); ovl_cls* oc = ovl_mgr_.get_ovl();
irp.bmRequestType = (type >> 5) & 0x03; irp.bmRequestType = (type >> 5) & 0x03;
irp.bRequest = req; irp.bRequest = req;
@ -723,7 +705,7 @@ int usb_device::transfer_control(uint8_t type, uint8_t req, uint16_t val, uint16
{ {
if (irp.fTransferDirectionIn) if (irp.fTransferDirectionIn)
{ {
GetOverlappedResult((HANDLE)handle_, oc->over_lapped(), oc->io_bytes(), TRUE); GetOverlappedResult((HANDLE)handle_, oc->over_lapped(), oc->io_bytes(), FALSE);
ret = *oc->io_bytes(); ret = *oc->io_bytes();
} }
else else
@ -760,7 +742,7 @@ int usb_device::transfer_interrupt(unsigned endpoint, unsigned char* data, int*
*length = 0; *length = 0;
if (h) if (h)
{ {
ovl_cls* oc = ovl_mgr_.get_ovl(endpoint); 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())) if (DeviceIoControl(h, IOCTL_WAIT_ON_DEVICE_EVENT, NULL, 0, data, len, oc->io_bytes(), oc->over_lapped()))
{ {
ret = LIBUSB_SUCCESS; ret = LIBUSB_SUCCESS;
@ -773,7 +755,7 @@ int usb_device::transfer_interrupt(unsigned endpoint, unsigned char* data, int*
{ {
if (WaitForSingleObject(oc->over_lapped()->hEvent, timeout) == WAIT_OBJECT_0) if (WaitForSingleObject(oc->over_lapped()->hEvent, timeout) == WAIT_OBJECT_0)
{ {
GetOverlappedResult(h, oc->over_lapped(), oc->io_bytes(), TRUE); GetOverlappedResult(h, oc->over_lapped(), oc->io_bytes(), FALSE);
*length = *oc->io_bytes(); *length = *oc->io_bytes();
ret = LIBUSB_SUCCESS; ret = LIBUSB_SUCCESS;
} }
@ -797,17 +779,6 @@ int usb_device::transfer_interrupt(unsigned endpoint, unsigned char* data, int*
return ret; return ret;
} }
int usb_device::cancel_io(void)
{
for (auto& v : pipes_)
{
CancelIo(v.pipe);
}
ovl_mgr_.notify_all();
return LIBUSB_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// usb_monitor ... // usb_monitor ...
@ -859,7 +830,7 @@ int usb_monitor::enum_usb_device(bool(__stdcall* found_usb)(LPUSBDEV dev, void*
if (SetupDiGetDeviceRegistryPropertyW(dev_info, &sdd, SPDRP_DRIVER, NULL, (PBYTE)buf->DevicePath, len, &len)) // driver key if (SetupDiGetDeviceRegistryPropertyW(dev_info, &sdd, SPDRP_DRIVER, NULL, (PBYTE)buf->DevicePath, len, &len)) // driver key
dev.driver_key = u2utf8(buf->DevicePath); dev.driver_key = u2utf8(buf->DevicePath);
len = size; len = size;
if(SetupDiGetDeviceRegistryPropertyW(dev_info, &sdd, SPDRP_DEVICEDESC, NULL, (PBYTE)buf->DevicePath, len, &len)) // device description if (SetupDiGetDeviceRegistryPropertyW(dev_info, &sdd, SPDRP_DEVICEDESC, NULL, (PBYTE)buf->DevicePath, len, &len)) // device description
dev.desc = u2utf8(buf->DevicePath); dev.desc = u2utf8(buf->DevicePath);
len = size; len = size;
if (SetupDiGetDeviceRegistryPropertyW(dev_info, &sdd, SPDRP_ADDRESS, NULL, (PBYTE)buf->DevicePath, len, &len)) // device description if (SetupDiGetDeviceRegistryPropertyW(dev_info, &sdd, SPDRP_ADDRESS, NULL, (PBYTE)buf->DevicePath, len, &len)) // device description
@ -981,7 +952,7 @@ void usb_monitor::notify_usb_event(usb_device*& dev, bool arrive)
if (arrive) if (arrive)
{ {
bool found = false; bool found = false;
for(size_t i = 0; i < devices_.size(); ++i) for (size_t i = 0; i < devices_.size(); ++i)
{ {
// if (devices_[i]->name() == dev->name()) // if (devices_[i]->name() == dev->name())
if (stricmp(usb_device::name_without_guid(devices_[i]->name().c_str()).c_str(), noguid.c_str()) == 0) if (stricmp(usb_device::name_without_guid(devices_[i]->name().c_str()).c_str(), noguid.c_str()) == 0)
@ -1157,7 +1128,7 @@ void usb_monitor::thread_run_device_event_wnd(void)
wnd_monitor_ = CreateWindowW(cls, L"usb", WS_POPUP, 0, 0, 0, 0, NULL, NULL, GetModuleHandleW(NULL), this); wnd_monitor_ = CreateWindowW(cls, L"usb", WS_POPUP, 0, 0, 0, 0, NULL, NULL, GetModuleHandleW(NULL), this);
if (!IsWindow(wnd_monitor_)) if (!IsWindow(wnd_monitor_))
{ {
if(run_) if (run_)
Sleep(1000); Sleep(1000);
return; return;
@ -1254,7 +1225,7 @@ int LIBUSB_CALL libusb_init(libusb_context** ctx)
{ {
if (ctx) if (ctx)
*ctx = (libusb_context*)new usb_monitor(); *ctx = (libusb_context*)new usb_monitor();
else if(!usb_monitor::usb_monitor_) else if (!usb_monitor::usb_monitor_)
usb_monitor::usb_monitor_ = new usb_monitor(); usb_monitor::usb_monitor_ = new usb_monitor();
return LIBUSB_SUCCESS; return LIBUSB_SUCCESS;
@ -1490,12 +1461,9 @@ void LIBUSB_CALL libusb_quit(libusb_context* ctx)
} }
uint8_t LIBUSB_CALL libusb_get_device_address(libusb_device* device) uint8_t LIBUSB_CALL libusb_get_device_address(libusb_device* device)
{ {
if(!device) if (!device)
return 0; return 0;
return ((usb_device*)device)->address(); return ((usb_device*)device)->address();
} }
int LIBUSB_CALL libusb_cancel_transfer(struct libusb_transfer* transfer/*in windows, this is a libusb_device* object*/)
{
return ((usb_device*)transfer)->cancel_io();
}

View File

@ -48,10 +48,9 @@ class ovl_cls// : public refer
volatile long ref_; volatile long ref_;
OVERLAPPED ovl_; OVERLAPPED ovl_;
DWORD io_bytes_; DWORD io_bytes_;
uint32_t type_;
public: public:
ovl_cls(uint32_t type); ovl_cls();
protected: protected:
~ovl_cls(); ~ovl_cls();
@ -74,8 +73,6 @@ public:
LPDWORD io_bytes(void); LPDWORD io_bytes(void);
void reset(void); void reset(void);
bool is_waited(void); bool is_waited(void);
void notify(void);
uint32_t type(void);
}; };
class ovl_mgr class ovl_mgr
{ {
@ -87,8 +84,7 @@ public:
~ovl_mgr(); ~ovl_mgr();
public: public:
ovl_cls* get_ovl(uint32_t type); ovl_cls* get_ovl(void);
void notify_all(void);
}; };
class usb_device // consider as libusb_device class usb_device // consider as libusb_device
@ -100,8 +96,8 @@ class usb_device // consider as libusb_device
bool online_; bool online_;
ovl_mgr ovl_mgr_; ovl_mgr ovl_mgr_;
libusb_device_handle *handle_; // as file handle returned by CreateFile libusb_device_handle* handle_; // as file handle returned by CreateFile
libusb_device_descriptor *dev_desc_; libusb_device_descriptor* dev_desc_;
std::vector<libusb_config_descriptor*> cfg_desc_; std::vector<libusb_config_descriptor*> cfg_desc_;
typedef struct _usb_pipe typedef struct _usb_pipe
@ -119,10 +115,10 @@ class usb_device // consider as libusb_device
public: public:
usb_device(const USBDEV& dev); usb_device(const USBDEV& dev);
static void vid_pid_from_name(const char* name, int *vid, int *pid); // device name like '\\?\usb#vid_3072&pid_0239#01234567aabbccddee#{a5dcbf10-6530-11d2-901f-00c04fb951ed}' static void vid_pid_from_name(const char* name, int* vid, int* pid); // device name like '\\?\usb#vid_3072&pid_0239#01234567aabbccddee#{a5dcbf10-6530-11d2-901f-00c04fb951ed}'
static DWORD from_hex_string(const char* hex_str); static DWORD from_hex_string(const char* hex_str);
static std::string name_without_guid(const char* name); static std::string name_without_guid(const char* name);
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*/, std::string* reg_key/*{6bdd1fc6-810f-11d0-bec7-08002be2092f}\\0007*/); 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*/, std::string* reg_key/*{6bdd1fc6-810f-11d0-bec7-08002be2092f}\\0007*/);
static std::string usb_scan_name(const char* reg_key/*{6bdd1fc6-810f-11d0-bec7-08002be2092f}\\0007*/); // return \\.\Usbscan1 ... static std::string usb_scan_name(const char* reg_key/*{6bdd1fc6-810f-11d0-bec7-08002be2092f}\\0007*/); // return \\.\Usbscan1 ...
long add_ref(void); long add_ref(void);
@ -157,8 +153,6 @@ public:
int transfer_bulk(unsigned endpoint, unsigned char* data, int* length, unsigned int timeout); 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_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); int transfer_interrupt(unsigned endpoint, unsigned char* data, int* length, unsigned int timeout);
int cancel_io(void);
}; };
class usb_callback class usb_callback
{ {