更改USB设备标识,以不带GUID后缀的设备名称为判断依据

This commit is contained in:
gb 2022-10-24 16:17:32 +08:00
parent 9f33e4db85
commit aa5c9ad904
2 changed files with 244 additions and 395 deletions

View File

@ -146,15 +146,10 @@ ovl_cls* ovl_mgr::get_ovl(void)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// usb_device ...
usb_device::usb_device(const char* name) : ref_(1), name_(name ? name : ""), is_ok_(false)
, dev_desc_(NULL), handle_(NULL), online_(true), timout_ms_(1000), reg_key_("")
usb_device::usb_device(const USBDEV& dev) : ref_(1), udev_(dev), is_ok_(false)
, dev_desc_(NULL), handle_(NULL), online_(true), timout_ms_(1000)
{
bzero(&guid_, sizeof(guid_));
id_ = usb_device::vid_pid_from_name(name);
GUID guid;
UuidFromStringA((RPC_CSTR)HG_SCANNER_GUID, &guid);
id_.addr = usb_device::get_device_address(name_.c_str(), &guid);
memset(&guid_, 0, sizeof(guid_));
}
usb_device::~usb_device()
{
@ -202,23 +197,20 @@ int usb_device::set_timeout(HANDLE h)
//SetCommTimeouts(h, &to);
}
DEVID usb_device::vid_pid_from_name(const char* name)
void usb_device::vid_pid_from_name(const char* name, int* vid, int* pid)
{
// name: \\?\usb#vid_3072&pid_0239#01234567aabbccddee#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
DEVID id;
std::string s(name ? name : "");
size_t pos = 0;
std::transform(s.begin(), s.end(), s.begin(), tolower);
pos = s.find("vid_");
if (pos != std::string::npos)
id.vid = usb_device::from_hex_string(s.c_str() + pos + 4);
if (pos != std::string::npos && vid)
*vid = usb_device::from_hex_string(s.c_str() + pos + 4);
pos = s.find("pid_");
if (pos != std::string::npos)
id.pid = usb_device::from_hex_string(s.c_str() + pos + 4);
return id;
if (pos != std::string::npos && pid)
*pid = usb_device::from_hex_string(s.c_str() + pos + 4);
}
DWORD usb_device::from_hex_string(const char* hex_str)
{
@ -242,222 +234,15 @@ DWORD usb_device::from_hex_string(const char* hex_str)
return v;
}
std::string usb_device::driver_key_name(HANDLE file)
std::string usb_device::name_without_guid(const char* name)
{
ULONG nBytes = 0;
USB_HCD_DRIVERKEY_NAME driverKeyName = { 0 };
BOOL success = DeviceIoControl(file, IOCTL_GET_HCD_DRIVERKEY_NAME, &driverKeyName, sizeof(driverKeyName), &driverKeyName, sizeof(driverKeyName), &nBytes, NULL);
std::string ret("");
std::string no_guid(name);
size_t pos = no_guid.find("#{");
if (success && driverKeyName.ActualLength > nBytes)
{
PUSB_HCD_DRIVERKEY_NAME buf = (PUSB_HCD_DRIVERKEY_NAME)GlobalAlloc(GPTR, driverKeyName.ActualLength);
nBytes = driverKeyName.ActualLength;
success = DeviceIoControl(file, IOCTL_GET_HCD_DRIVERKEY_NAME, &buf, nBytes, &buf, nBytes, &nBytes, NULL);
if (success)
{
ret = u2utf8(buf->DriverKeyName);
}
GlobalFree(buf);
}
if (pos != std::string::npos)
no_guid.erase(pos);
return ret;
}
std::string usb_device::parent_hub_path_name(int vid, int pid, int *addr, std::string* reg_key)
{
std::string ret("");
GUID guid = GUID_DEVINTERFACE_USB_HUB;
HDEVINFO dev = SetupDiGetClassDevsW(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
int port = addr ? *addr : -1;
if (dev)
{
SP_DEVICE_INTERFACE_DATA id = { 0 };
SP_DEVINFO_DATA did;
int ind = 0;
id.cbSize = sizeof(id);
while (SetupDiEnumDeviceInterfaces(dev, NULL, &guid, ind++, &id))
{
PSP_DEVICE_INTERFACE_DETAIL_DATA_W buf = NULL;
DWORD size = 0;
if (!SetupDiGetDeviceInterfaceDetailW(dev, &id, buf, 0, &size, NULL) &&
GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
int bytes = size + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + 40;
buf = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)new wchar_t[bytes];
memset(buf, 0, bytes * 2);
buf->cbSize = sizeof(*buf);
if (SetupDiGetDeviceInterfaceDetailW(dev, &id, buf, buf->cbSize + size, NULL, NULL))
{
std::string n(u2utf8(buf->DevicePath));
if (find_vid_pid_in_hub(n.c_str(), vid, pid, &port, reg_key))
ret = n;
}
delete[] buf;
if (ret.length())
break;
}
}
SetupDiDestroyDeviceInfoList(dev);
}
if (addr)
*addr = port;
VLOG_MINI_4(LOG_LEVEL_DEBUG_INFO, "Parent hub for %04X:%04X is: %s (+%d)\r\n", vid, pid, ret.c_str(), port);
return ret;
}
bool usb_device::find_vid_pid_in_hub(const char* utf8_hub_path_name, int vid, int pid, int* addr, std::string* reg_key)
{
bool ret = false;
HANDLE h = CreateFileA(utf8_hub_path_name, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (h == INVALID_HANDLE_VALUE)
return ret;
int bytes = sizeof(USB_NODE_CONNECTION_INFORMATION_EX) + (sizeof(USB_PIPE_INFO) * 30);
PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfoEx = (PUSB_NODE_CONNECTION_INFORMATION_EX)new char[bytes];
memset(connectionInfoEx, 0, bytes);
if (addr && *addr != -1)
{
connectionInfoEx->ConnectionIndex = *addr;
DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, connectionInfoEx,
bytes, connectionInfoEx, bytes, (LPDWORD)&bytes, NULL);
ret = connectionInfoEx->DeviceDescriptor.idVendor == vid && connectionInfoEx->DeviceDescriptor.idProduct == pid;
if (ret && reg_key)
{
char buf[512] = { 0 };
USB_NODE_CONNECTION_DRIVERKEY_NAME* name = (USB_NODE_CONNECTION_DRIVERKEY_NAME*)buf;
name->ConnectionIndex = *addr;
name->ActualLength = (sizeof(buf) - sizeof(*name)) / 2 - 1;
DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, name, sizeof(*name), name, name->ActualLength, (LPDWORD)&bytes, NULL);
*reg_key = u2utf8(name->DriverKeyName);
}
}
else
{
for (int i = 1; !ret; ++i)
{
DWORD len = bytes;
connectionInfoEx->ConnectionIndex = i;
if (!DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, connectionInfoEx,
bytes, connectionInfoEx, bytes, (LPDWORD)&bytes, NULL))
break;
ret = connectionInfoEx->DeviceDescriptor.idVendor == vid && connectionInfoEx->DeviceDescriptor.idProduct == pid;
}
if (ret && addr)
*addr = connectionInfoEx->ConnectionIndex;
}
delete[] connectionInfoEx;
CloseHandle(h);
return ret;
}
int usb_device::get_device_address(const char* device_name, LPGUID lpguid)
{
int addr = -1;
GUID guid = lpguid ? *lpguid : GUID_DEVINTERFACE_USB_DEVICE;
HDEVINFO dev = NULL;
std::string ret(""), src(device_name);
dev = SetupDiGetClassDevsW(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (dev)
{
SP_DEVICE_INTERFACE_DATA id = { 0 };
SP_DEVINFO_DATA did;
int ind = 0;
size_t pos = src.find("{");
if (pos != std::string::npos)
src.erase(pos);
id.cbSize = sizeof(id);
while (SetupDiEnumDeviceInterfaces(dev, NULL, &guid, ind++, &id))
{
PSP_DEVICE_INTERFACE_DETAIL_DATA_W buf = NULL;
DWORD size = 0;
ret = "";
if (!SetupDiGetDeviceInterfaceDetailW(dev, &id, buf, 0, &size, NULL) &&
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, &id, buf, buf->cbSize + size, NULL, NULL))
{
wchar_t* l = wcsstr(buf->DevicePath, L"{");
if (l)
*l = 0;
ret = u2utf8(buf->DevicePath);
}
delete buf;
}
if (stricmp(ret.c_str(), src.c_str()))
continue;
SP_DEVINFO_DATA dd = { 0 };
dd.cbSize = sizeof(dd);
// for (int i = 0; SetupDiEnumDeviceInfo(dev_info, i, &dd); ++i)
if (SetupDiEnumDeviceInfo(dev, ind - 1, &dd))
{
SetupDiGetDeviceRegistryPropertyA(dev, &dd, SPDRP_ADDRESS, NULL, (PBYTE)&addr, sizeof(addr), NULL);
}
break;
}
SetupDiDestroyDeviceInfoList(dev);
}
return addr;
}
std::string usb_device::usb_scan_name(DEVID id, const char* guid)
{
// HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}
HKEY key = NULL, root = NULL;
std::string path("SYSTEM\\CurrentControlSet\\Control\\Class\\{"), name("");
char val[256] = { 0 };
int ind = 0, err = 0;
path += guid;
path += "}";
err = RegOpenKeyA(HKEY_LOCAL_MACHINE, path.c_str(), &root);
if (root)
{
DWORD index = 0;
while (RegEnumKeyA(root, index++, val, _countof(val) - 1) == ERROR_SUCCESS)
{
RegOpenKeyA(root, val, &key);
if (key)
{
DWORD len = _countof(val) - 1,
type = REG_SZ;
if (RegQueryValueExA(key, "MatchingDeviceId", NULL, &type, (LPBYTE)val, &len) == ERROR_SUCCESS)
{
val[len] = 0;
DEVID cid = usb_device::vid_pid_from_name(val);
if (cid.vid == id.vid && cid.pid == id.pid)
{
len = _countof(val) - 1;
type = REG_SZ;
if (RegQueryValueExA(key, "CreateFileName", NULL, &type, (LPBYTE)val, &len) == ERROR_SUCCESS)
{
val[len] = 0;
name = val;
}
}
}
RegCloseKey(key);
if (!name.empty())
break;
}
memset(val, 0, sizeof(val));
}
RegCloseKey(root);
}
return name;
return no_guid;
}
std::string usb_device::usb_scan_name(const char* reg_key)
{
@ -496,21 +281,6 @@ long usb_device::release(void)
return ref;
}
bool usb_device::operator==(const char* name)
{
return name_ == name;
}
bool usb_device::operator==(const DEVID& id)
{
return id_.vid == id.vid && id_.pid == id.pid;
}
usb_device& usb_device::operator=(const DEVID& id)
{
id_ = id;
return *this;
}
usb_device& usb_device::operator=(const GUID& guid)
{
guid_ = guid;
@ -520,16 +290,16 @@ usb_device& usb_device::operator=(const GUID& guid)
std::string usb_device::name(void)
{
return name_;
return udev_.name;
}
USBDEV& usb_device::dev(void)
{
return udev_;
}
GUID usb_device::guid(void)
{
return guid_;
}
DEVID usb_device::id(void)
{
return id_;
}
bool usb_device::is_ok(void)
{
return is_ok_;
@ -545,40 +315,41 @@ bool usb_device::is_online(void)
void usb_device::set_online(bool online)
{
online_ = online;
if (!online_)
reg_key_ = "";
}
uint8_t usb_device::port(void)
{
if (!dev_desc_)
init();
return port_;
return udev_.port;
}
uint8_t usb_device::address(void)
{
if (!dev_desc_)
init();
return udev_.addr;
}
std::string usb_device::reg_path(void)
{
return reg_key_;
return udev_.driver_key;
}
bool usb_device::init(void)
{
PUSBDEVICEINFO info = NULL;
GUID guid;
int addr = -1;
clear();
UuidFromStringA((RPC_CSTR)HG_SCANNER_GUID, &guid);
addr = usb_device::get_device_address(name_.c_str(), &guid);
//if (addr != -1)
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())
{
std::string path(usb_device::parent_hub_path_name(id_.vid, id_.pid, &addr, &reg_key_));
if (!path.empty())
HANDLE h = CreateFileA(udev_.hub.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (h != INVALID_HANDLE_VALUE)
{
HANDLE h = CreateFileA(path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (h != INVALID_HANDLE_VALUE)
{
info = enumerate_hub_port(h, addr);
CloseHandle(h);
}
info = enumerate_hub_port(h, udev_.port);
CloseHandle(h);
}
}
@ -587,7 +358,7 @@ bool usb_device::init(void)
if (info)
{
port_ = addr;
udev_.addr = info->ConnectionInfo->DeviceAddress;
if (info->ConnectionInfo)
{
dev_desc_ = new libusb_device_descriptor;
@ -681,7 +452,6 @@ bool usb_device::init(void)
free_usb_device_info(info);
}
id_.addr = port_;
return is_ok_;
}
@ -709,10 +479,6 @@ void usb_device::clear(void)
cfg_desc_.clear();
is_ok_ = false;
}
void usb_device::online_statu_changed(bool online)
{
online_ = online;
}
int usb_device::get_descriptor(libusb_device_descriptor* desc)
{
if (dev_desc_)
@ -731,8 +497,8 @@ int usb_device::get_descriptor(libusb_device_descriptor* desc)
desc->bDeviceClass = libusb_class_code::LIBUSB_CLASS_HID;
else
desc->bDeviceClass = libusb_class_code::LIBUSB_CLASS_VENDOR_SPEC;
desc->idVendor = id_.vid;
desc->idProduct = id_.pid;
desc->idVendor = udev_.vid;
desc->idProduct = udev_.pid;
desc->bcdUSB = 0x200; // USB2.0 ?
desc->bcdDevice = 0; // ?
desc->bDescriptorType = libusb_descriptor_type::LIBUSB_DT_DEVICE;
@ -765,7 +531,7 @@ int usb_device::open(libusb_device_handle** dev_handle)
if (!dev_desc_)
init();
HANDLE h = open_usb(name_.c_str());
HANDLE h = open_usb(udev_.name.c_str());
if (h == INVALID_HANDLE_VALUE)
{
*dev_handle = NULL;
@ -775,22 +541,19 @@ int usb_device::open(libusb_device_handle** dev_handle)
USBSCAN_PIPE_CONFIGURATION upc = { 0 };
DWORD cbr = 0;
std::string fmt("\\%d"), root(""); // (usb_device::usb_scan_name(reg_key_.empty() ? id_ : reg_key_.c_str()));
if (reg_key_.length())
root = usb_device::usb_scan_name(reg_key_.c_str());
if (root.empty())
root = usb_device::usb_scan_name(id_);
std::string fmt("\\%d"), root("");
if (udev_.driver_key.length())
root = usb_device::usb_scan_name(udev_.driver_key.c_str());
if (root.empty())
{
VLOG_MINI_1(LOG_LEVEL_WARNING, "Cannot find '\\\\.\\Usbscan' name for '%s', try run in Administrator!\r\n", name_.c_str());
root = name_;
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;
fmt = "\\%04d";
}
else
{
VLOG_MINI_2(LOG_LEVEL_WARNING, "Nice: '%s' for '%s'.\r\n", root.c_str(), name_.c_str());
VLOG_MINI_2(LOG_LEVEL_WARNING, "Nice: '%s' for '%s'.\r\n", root.c_str(), udev_.name.c_str());
}
if (DeviceIoControl(h, IOCTL_GET_PIPE_CONFIGURATION, NULL, 0, &upc, sizeof(upc), &cbr, NULL))
{
@ -1018,6 +781,121 @@ 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;
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)
{
return vid == PRODUCT_VID || vid == PRODUCT_VENDOR_HG1;
}
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);
@ -1056,20 +934,15 @@ void usb_monitor::notify_usb_event(usb_device*& dev, bool arrive)
{
std::lock_guard<std::mutex> lock(lock_);
int ev = arrive ? LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED : LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT;
DEVID id = dev->id();
if (id.vid != PRODUCT_VID && id.vid != PRODUCT_VENDOR_HG1)
return;
VLOG_MINI_4(LOG_LEVEL_DEBUG_INFO, "WINUSB %04X:%04X(%d) %s\r\n", dev->id().vid, dev->id().pid, dev->id().addr,
arrive ? "Connected" : "Left");
std::string noguid(usb_device::name_without_guid(dev->name().c_str()));
if (arrive)
{
bool found = false;
for(size_t i = 0; i < devices_.size(); ++i)
{
if (devices_[i]->id() == id)
// 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 (devices_[i]->is_online())
{
@ -1079,6 +952,8 @@ void usb_monitor::notify_usb_event(usb_device*& dev, bool arrive)
}
else
{
devices_[i]->clear();
devices_[i]->dev() = dev->dev(); // use NEW connection info ...
dev->release();
dev = devices_[i];
dev->add_ref();
@ -1097,36 +972,25 @@ void usb_monitor::notify_usb_event(usb_device*& dev, bool arrive)
else
{
bool discard = false;
for (size_t i = 0; i < devices_.size(); ++i)
{
if (devices_[i]->id().vid != id.vid || devices_[i]->id().pid != id.pid)
continue;
if (devices_[i]->reg_path().empty() || usb_device::usb_scan_name(devices_[i]->reg_path().c_str()).empty())
// if (devices_[i]->name() == dev->name())
if (stricmp(usb_device::name_without_guid(devices_[i]->name().c_str()).c_str(), noguid.c_str()) == 0)
{
dev->release();
dev = devices_[i];
dev->add_ref();
// if (dev->is_open())
if (dev->is_online())
{
if (dev->is_online())
{
dev->set_online(false);
discard = false;
break;
}
else
{
// VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "%s is already offline and received LEAVE again, discard this event.\n", dev->name().c_str());
// dev->release();
// return;
discard = true;
}
dev->set_online(false);
discard = false;
}
//else
//{
// devices_.erase(devices_.begin() + i);
// dev->release();
//}
else
{
discard = true;
}
break;
}
}
if (discard)
@ -1153,67 +1017,54 @@ int usb_monitor::on_usb_pnp(WPARAM wp, LPARAM lp)
return wp == DBT_DEVICEQUERYREMOVE;
}
std::string utf8(u2utf8(dev->dbcc_name));
if (wp == DBT_DEVICEQUERYREMOVE)
return cur_dev_name_ != u2utf8(dev->dbcc_name);
return cur_dev_name_ != utf8;
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "event '%08x' of device %s\n", wp, u2utf8(dev->dbcc_name).c_str());
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "event '%08x' of device %s\n", wp, utf8.c_str());
usb_device* ud = new usb_device(u2utf8(dev->dbcc_name).c_str());
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;
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);
*ud = dev->dbcc_classguid;
if (!PostThreadMessageW(handle_msg_id_, MSG_DEVICE_PNP, wp == DBT_DEVICEARRIVAL, (LPARAM)ud))
ud->release();
return ret;
}
void usb_monitor::find_usb(std::vector<std::string>& usb_devs)
{
GUID hid = GUID_DEVINTERFACE_USB_DEVICE; // GUID_DEVINTERFACE_USB_HUB
HDEVINFO dev_info = NULL;
int ind = 0;
SP_DEVICE_INTERFACE_DATA id = { 0 };
// HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\DeviceClasses\{a5dcbf10-6530-11d2-901f-00c04fb951ed}
// HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\USB
// UuidFromStringW((RPC_WSTR)WIN_USB_GUID, &hid);
dev_info = SetupDiGetClassDevsW(&hid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (!dev_info)
return;
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))
{
usb_devs.push_back(u2utf8(buf->DevicePath));
}
delete[](char*)buf;
}
id.cbSize = sizeof(id);
}
SetupDiDestroyDeviceInfoList(dev_info);
}
void usb_monitor::find_usb_and_trigger_event(void)
{
std::vector<std::string> old(found_usb_devs_);
std::vector<USBDEV> old(found_usb_devs_);
found_usb_devs_.clear();
find_usb(found_usb_devs_);
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)
{
std::vector<std::string>::iterator it = std::find(old.begin(), old.end(), found_usb_devs_[i]);
if (!usb_monitor::is_desired_usb_device(found_usb_devs_[i].vid, found_usb_devs_[i].pid))
{
found_usb_devs_.erase(found_usb_devs_.begin() + i);
i--;
}
}
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].c_str());
usb_device* dev = new usb_device(found_usb_devs_[i]);
notify_usb_event(dev, true);
dev->release();
}
@ -1223,7 +1074,7 @@ void usb_monitor::find_usb_and_trigger_event(void)
for (size_t i = 0; i < old.size(); ++i)
{
usb_device* dev = new usb_device(old[i].c_str());
usb_device* dev = new usb_device(old[i]);
notify_usb_event(dev, false);
dev->release();
}
@ -1276,13 +1127,8 @@ void usb_monitor::thread_run_device_event_wnd(void)
DEV_BROADCAST_HDR dbh = { 0 };
HDEVNOTIFY notify = NULL;
find_usb(found_usb_devs_);
for (size_t i = 0; i < found_usb_devs_.size(); ++i)
{
usb_device* dev = new usb_device(found_usb_devs_[i].c_str());
notify_usb_event(dev, true);
dev->release();
}
// mannual triggered at beginning ...
find_usb_and_trigger_event();
dbh.dbch_size = sizeof(dbh);
dbh.dbch_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
@ -1292,7 +1138,7 @@ void usb_monitor::thread_run_device_event_wnd(void)
DEV_BROADCAST_DEVICEINTERFACE_A di = { 0 };
di.dbcc_size = (sizeof(di) + 3) / 4 * 4;
di.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
UuidFromStringA((RPC_CSTR)HG_SCANNER_GUID, &di.dbcc_classguid);
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)
@ -1605,6 +1451,6 @@ uint8_t LIBUSB_CALL libusb_get_device_address(libusb_device* device)
if(!device)
return 0;
return ((usb_device*)device)->port();
return ((usb_device*)device)->address();
}

View File

@ -15,25 +15,33 @@
// HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{6bdd1fc6-810f-11d0-bec7-08002be2092f}
#define HG_SCANNER_GUID "6BDD1FC6-810F-11D0-BEC7-08002BE2092F"
#define IMAGE_CLASS_GUID "6BDD1FC6-810F-11D0-BEC7-08002BE2092F"
#define MONITOR_WINDOW_OWNER L"monitor_wnd_owner"
typedef struct _dev_id
typedef struct _usb_dev
{
int vid;
int pid;
int addr;
// all members are in utf8
std::string name; // \\?\usb#vid_0bda&pid_0129#20100201396000000#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
std::string driver_key; // {6bdd1fc6-810f-11d0-bec7-08002be2092f}\\0016
std::string desc; // USB Composite Device
std::string hub; // parent hub
int vid;
int pid;
int port; // port on the hub, also be ConnectionIndex
int addr; // connection address
struct _dev_id()
struct _usb_dev()
{
memset(this, 0, sizeof(struct _dev_id));
name = driver_key = desc = hub = "";
vid = pid = port = 0;
addr = -1;
}
bool operator==(const struct _dev_id& r)
bool operator==(const struct _usb_dev& r)
{
return vid == r.vid && pid == r.pid && r.addr == addr;
return name == r.name;
}
}DEVID;
}USBDEV, * LPUSBDEV;
class ovl_cls// : public refer
{
@ -83,12 +91,9 @@ class usb_device // consider as libusb_device
{
volatile long ref_;
GUID guid_;
std::string name_;
std::string reg_key_;
DEVID id_;
USBDEV udev_;
bool is_ok_;
bool online_;
uint8_t port_;
ovl_mgr ovl_mgr_;
libusb_device_handle *handle_; // as file handle returned by CreateFile
@ -108,15 +113,12 @@ class usb_device // consider as libusb_device
int set_timeout(HANDLE h);
public:
usb_device(const char* name);
usb_device(const USBDEV& dev);
static DEVID vid_pid_from_name(const char* name); // 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 std::string driver_key_name(HANDLE file);
static std::string parent_hub_path_name(int vid, int pid, int *addr = NULL, std::string* reg_key = NULL);
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 int get_device_address(const char* device_name, LPGUID lpguid);
static std::string usb_scan_name(DEVID id, const char* guid = HG_SCANNER_GUID); // return \\.\Usbscan1 ...
static std::string usb_scan_name(const char* reg_key/*{6bdd1fc6-810f-11d0-bec7-08002be2092f}\\0007*/); // return \\.\Usbscan1 ...
long add_ref(void);
@ -126,25 +128,21 @@ 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);
USBDEV& dev(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);
uint8_t address(void);
std::string reg_path(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);
@ -178,14 +176,13 @@ class usb_monitor // consider as libusb_context
HWND wnd_monitor_;
std::string cur_dev_name_;
volatile bool run_;
std::vector<std::string> found_usb_devs_;
std::vector<USBDEV> found_usb_devs_;
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);
void find_usb_and_trigger_event(void);
public:
@ -195,6 +192,12 @@ public:
static usb_monitor* usb_monitor_;
static UINT find_usb_timer_; // set when RegisterDeviceNotification failed
static int enum_usb_device(bool(__stdcall* found_usb)(LPUSBDEV dev, void* param), void* param, bool hub = false);
static bool __stdcall find_all_usb_devices(LPUSBDEV dev, void* param/*std::vector<USBDEV>* */);
static bool __stdcall usb_dev_by_name(LPUSBDEV dev, void* param/*LPUSBDEV*/);
static bool __stdcall find_parent_hub(LPUSBDEV hub, void* param/*LPUSBDEV*/);
static bool is_desired_usb_device(int vid, int pid);
public:
usb_callback* reg_callback(libusb_hotplug_callback_fn cb, void* param);
void unreg_callback(usb_callback* cb);