更改USB设备标识,以不带GUID后缀的设备名称为判断依据
This commit is contained in:
parent
9f33e4db85
commit
aa5c9ad904
|
@ -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, ®_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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue