Get device path based on USB VID:PID in Linux
libusb can't get it actually. So look at this file instead: /proc/bus/input/devices
Example line from the file:
I: Bus=0003 Vendor=1a2c Product=0c23 Version=0110
N: Name="USB USB Keyboard"
P: Phys=usb-0000:00:14.0-3/input0
S: Sysfs=/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.0/0003:1A2C:0C23.0015/input/input30
U: Uniq=
H: Handlers=sysrq kbd event10 leds
B: PROP=0
B: EV=120013
B: KEY=1000000000007 ff800000000007ff febeffdff3cfffff fffffffffffffffe
B: MSC=10
B: LED=7
This function gets the event number from the device with the matching VID:PID:
#include <string>
#include <iostream>
#include <fstream>
void open_device (std::string device_vid, std::string device_pid)
{
try
{
std::ifstream file_input;
std::size_t pos;
std::string device_path, current_line, search_str, event_str;
std::string device_list_file = "/proc/bus/input/devices";
bool vid_pid_found = false;
int fd = 0;
bool debug = true;
// 1. open device list file
file_input.open(device_list_file.c_str());
if (!file_input.is_open())
{
std::cerr << "file_input.open >> " << std::strerror(errno) << std::endl;
throw -2;
}
// 2. search for first VID:PID and get event number
search_str = "Vendor=" + device_vid + " Product=" + device_pid;
while (getline(file_input, current_line))
{
if (!vid_pid_found)
{
pos = current_line.find(search_str, 0);
if (pos != std::string::npos)
{
vid_pid_found = true;
search_str = "event";
}
}
else
{
pos = current_line.find(search_str, 0);
if (pos != std::string::npos)
{
event_str = current_line.substr(pos);
// find space and substring event##
pos = event_str.find(' ', 0);
event_str = event_str.substr(0, pos);
break;
}
}
}
// 3. build device path
device_path = "/dev/input/" + event_str;
if (debug) std::cout << "device_path = " << device_path << std::endl;
// 4. connect to device
fd = open (device_path.c_str(), O_RDONLY);
if (fd < 0)
{
std::cerr << "open >> errno = " << std::strerror(errno) << std::endl;
throw -3;
}
}
catch (const std::exception &e)
{
std::cerr << "e.what() = " << e.what() << std::endl;
throw -1;
}
return;
}
Find /dev entry with VID/PID of USB device
you can use udevadm
for this
in the output of udevadm info -q property -n /dev/sd*
the VID is in the ID_VENDOR_ID
field and the PID is in the ID_MODEL_ID
field
you can extract this using grep / sed
...
How to determine sysfs devpath from USB device VID and PID in Python?
You might try using the sysfs path for usb devices, /sys/bus/usb/devices/, and globbing for the idProduct and idVendor files
/sys/bus/usb/devices/*/idProduct
/sys/bus/usb/devices/*/idVendor
How to get the USB VID, PID and serial number of a device in Ubuntu using C++ from /dev/xxx path
Here is a code snippet the does exactly what is being asked:
void ReadUsbIdentifiers(std::string dev_path){
auto udev = udev_new();
if (!udev) { return; }
struct stat statbuf;
if (stat(dev_path.c_str(), &statbuf) < 0) { return; }
auto type = S_ISBLK(statbuf.st_mode) ? 'b' : S_ISCHR(statbuf.st_mode) ? 'c' : 0;
auto opened_dev = udev_device_new_from_devnum(udev, type, statbuf.st_rdev);
auto dev = opened_dev;
while (dev != nullptr)
{
auto serial = udev_device_get_sysattr_value(dev, "serial");
if (nullptr == serial)
{
dev = udev_device_get_parent(dev);
}
else
{
std::cout << "VID: " << udev_device_get_sysattr_value(dev, "idVendor") << std::endl;
std::cout << "PID: " << udev_device_get_sysattr_value(dev, "idProduct") << std::endl;
std::cout << "Serial Number: " << serial << std::endl;
}
}
if (opened_dev) { udev_device_unref(opened_dev); }
udev_unref(udev);
}
There are two significant aspects to the code.
Firstly, you use the linux function stat() to get the /dev file’s status, and this status contains the st_rdev which is the device_ID. This can then be used in the UDEV function udev_device_new_from_devnum().
Secondly, the device returned by udev_device_new_from_devnum() is a ‘child’ of the physical USB device, and it does not itself know the serial number, vendor Id or product Id. Instead you need to get this information from the parent of the device, or the parent’s parent.
linux / libusb get usb device path
Since libusb 1.0.12, they have introduced libusb_get_port_path(), and in 1.0.16 replaced it with libusb_get_port_numbers() which allows you to query the bus topology.
Related Topics
How to Output the Actual Array in C++
Writing X264 from Opencv 3 with Ffmpeg on Linux
How to Convert a Tchar Array to Std::String
Cocreateinstance Returning E_Nointerface Even Though Interface Is Found
What Is a Cross-Platform Way to Get the Current Directory
Access Violation Writing Location 0Xcccccccc
Is It Okay to Use "And", "Or" etc. Instead of "&&", "||"
How to Check That I Didn't Break Anything When Refactoring
Capturing H264 Stream with Opencv
How to Debug C++11 Code with Unique_Ptr in Ddd (Or Gdb)
Can Virtual Functions Be Constexpr
What Exactly Is the Purpose of the (Asterisk) in Pointers
What Are the Different Character Sets Used For