Troubleshooting USB Communication with Qt and libusb for Embedded Device Recognition
-
I have an embedded USB device called 'Cruise Dongle USBP' with VID 0x0001 and PID 0x0002 (these values are just for testing) for which I loaded the WinUSB driver using Zadig.
Now I want to communicate with this device in Qt using the libusb library, but when I search for it, the library cannot find it.void USBDevice::ScanUsbDevices() { libusb_context *ctx = nullptr; libusb_device **device_list = nullptr; ssize_t count; if (libusb_init(&ctx) != 0) { qWarning() << "Error initializing libusb"; } // Get the device list count = libusb_get_device_list(ctx, &device_list); if (count < 0) { usbList->addItem("Error: Unable to get the device list."); libusb_exit(ctx); return; } qDebug() << "USB devices found:" << count; // usbList->addItem(QString("USB devices found: %1").arg(count)); // Iterate over the found devices for (ssize_t i = 0; i < count; i++) { libusb_device *device = device_list[i]; libusb_device_descriptor desc; if (libusb_get_device_descriptor(device, &desc) == 0) { QString info = QString("VID: 0x%1 PID: 0x%2") .arg(desc.idVendor, 4, 16, QChar('0')) .arg(desc.idProduct, 4, 16, QChar('0')); // Try to open the device to read extra information libusb_device_handle *handle; if (libusb_open(device, &handle) == 0) { unsigned char buffer[256]; if (desc.iManufacturer && libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, buffer, sizeof(buffer)) > 0) { info += " | Manufacturer: " + QString::fromUtf8(reinterpret_cast<char*>(buffer)); } if (desc.iProduct && libusb_get_string_descriptor_ascii(handle, desc.iProduct, buffer, sizeof(buffer)) > 0) { info += " | Product: " + QString::fromUtf8(reinterpret_cast<char*>(buffer)); } libusb_close(handle); } // usbList->addItem(info); qDebug() << info; } } // Free the device list libusb_free_device_list(device_list, 1); libusb_exit(ctx); }
that returns
AllK required contiguous memory = 675016 (64bit) 8 HotK Handles: HandleSize 2112 PoolSize 16912 (bytes) 64 LstK Handles: HandleSize 64 PoolSize 4112 (bytes) 2048 LstInfoK Handles: HandleSize 64 PoolSize 131088 (bytes) 128 UsbK Handles: HandleSize 96 PoolSize 12304 (bytes) 64 DevK Handles: HandleSize 112 PoolSize 7184 (bytes) 2048 OvlK Handles: HandleSize 104 PoolSize 213008 (bytes) 64 OvlPoolK Handles: HandleSize 96 PoolSize 6160 (bytes) 32 StmK Handles: HandleSize 176 PoolSize 5648 (bytes) 2048 IsochK Handles: HandleSize 136 PoolSize 278544 (bytes) Dynamically allocated as needed: KLST_DEVINFO = 2596 bytes each USB devices found: 6 "VID: 0x8086 PID: 0xa36d" "VID: 0x8087 PID: 0x0aaa" "VID: 0x10de PID: 0x1ada" "VID: 0x0b05 PID: 0x1866 | Manufacturer: ASUSTeK Computer Inc. | Product: N-KEY Device" "VID: 0x046d PID: 0xc01e | Manufacturer: Logitech | Product: USB-PS/2 Optical Mouse" "VID: 0x1366 PID: 0x1050"
I have tried reinstalling the drivers and changing them to Klibusb or others, but nothing works. Can anyone give me some advice?
-
@jsulm said in Troubleshooting USB Communication with Qt and libusb for Embedded Device Recognition:
@Andrew23 libusb is not part of Qt, you should consider asking there
Yes, I know, but I thought that maybe someone had encountered the same issue while implementing a Qt application that uses the libusb library.
@JoeCFD said in Troubleshooting USB Communication with Qt and libusb for Embedded Device Recognition:
And is it a better choice to use native Windows code to do the same job?
What do you mean? Sorry, but I’m a beginner in implementing USB communication between a device and an application.
-
@Andrew23 Try to use Qt serial port to detect USB Devices
#include <QCoreApplication> #include <QSerialPortInfo> #include <QDebug> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // List all available serial ports QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts(); foreach (const QSerialPortInfo &port, ports) { qDebug() << "Port:" << port.portName(); qDebug() << "Description:" << port.description(); qDebug() << "Manufacturer:" << port.manufacturer(); qDebug() << "Vendor ID:" << port.vendorIdentifier(); qDebug() << "Product ID:" << port.productIdentifier(); qDebug() << "-----------------------------------"; } return a.exec(); }
Open and Communicate with the USB Device
#include <QCoreApplication> #include <QSerialPort> #include <QSerialPortInfo> #include <QDebug> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // Create a serial port object QSerialPort serial; // Configure the serial port serial.setPortName("COM3"); // Replace with your device's port name serial.setBaudRate(QSerialPort::Baud9600); serial.setDataBits(QSerialPort::Data8); serial.setParity(QSerialPort::NoParity); serial.setStopBits(QSerialPort::OneStop); serial.setFlowControl(QSerialPort::NoFlowControl); // Open the serial port if (serial.open(QIODevice::ReadWrite)) { qDebug() << "Connected to" << serial.portName(); // Write data to the device QByteArray data = "Hello, USB Device!"; serial.write(data); qDebug() << "Data sent:" << data; // Read data from the device if (serial.waitForReadyRead(5000)) { // Wait for 5 seconds QByteArray response = serial.readAll(); qDebug() << "Response:" << response; } else { qDebug() << "Timeout: No response from device."; } // Close the serial port serial.close(); } else { qDebug() << "Failed to open port" << serial.portName(); } return a.exec(); }
If the code above does not work for you, try to find Windows API
#include <windows.h> #include <setupapi.h> #include <iostream> #include <string> #include <vector> #include <iomanip> #pragma comment(lib, "setupapi.lib") // Function to convert a wide string to a std::string std::string WideStringToString(const std::wstring& wideStr) { if (wideStr.empty()) return std::string(); int sizeNeeded = WideCharToMultiByte(CP_UTF8, 0, &wideStr[0], (int)wideStr.size(), nullptr, 0, nullptr, nullptr); std::string str(sizeNeeded, 0); WideCharToMultiByte(CP_UTF8, 0, &wideStr[0], (int)wideStr.size(), &str[0], sizeNeeded, nullptr, nullptr); return str; } // Function to enumerate USB devices void EnumerateUSBDevices() { HDEVINFO deviceInfoSet; SP_DEVINFO_DATA deviceInfoData; DWORD deviceIndex = 0; // Initialize the device information set for USB devices deviceInfoSet = SetupDiGetClassDevs(&GUID_DEVCLASS_USB, nullptr, nullptr, DIGCF_PRESENT | DIGCF_PROFILE); if (deviceInfoSet == INVALID_HANDLE_VALUE) { std::cerr << "Failed to get device information set." << std::endl; return; } // Initialize the device information structure deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); // Enumerate through all devices in the set while (SetupDiEnumDeviceInfo(deviceInfoSet, deviceIndex++, &deviceInfoData)) { // Get the device instance ID (contains VID and PID) wchar_t deviceID[256]; if (SetupDiGetDeviceInstanceId(deviceInfoSet, &deviceInfoData, deviceID, sizeof(deviceID) / sizeof(deviceID[0]), nullptr)) { std::wstring deviceIDStr(deviceID); std::string deviceIDUtf8 = WideStringToString(deviceIDStr); // Extract VID and PID from the device instance ID size_t vidPos = deviceIDUtf8.find("VID_"); size_t pidPos = deviceIDUtf8.find("PID_"); if (vidPos != std::string::npos && pidPos != std::string::npos) { std::string vid = deviceIDUtf8.substr(vidPos + 4, 4); std::string pid = deviceIDUtf8.substr(pidPos + 4, 4); std::cout << "Device ID: " << deviceIDUtf8 << std::endl; std::cout << "VID: " << vid << ", PID: " << pid << std::endl; } } // Get the device description wchar_t deviceDescription[256]; if (SetupDiGetDeviceRegistryProperty(deviceInfoSet, &deviceInfoData, SPDRP_FRIENDLYNAME, nullptr, (PBYTE)deviceDescription, sizeof(deviceDescription), nullptr)) { std::wstring descriptionStr(deviceDescription); std::string descriptionUtf8 = WideStringToString(descriptionStr); std::cout << "Description: " << descriptionUtf8 << std::endl; } std::cout << "-----------------------------------" << std::endl; } // Clean up SetupDiDestroyDeviceInfoList(deviceInfoSet); } int main() { EnumerateUSBDevices(); return 0; }
-
@JoeCFD said in Troubleshooting USB Communication with Qt and libusb for Embedded Device Recognition:
@Andrew23 Try to use Qt serial port to detect USB Devices
Maybe I didn't explain my context well. What you suggested is to open a serial connection with QSerialPort, but my USB device is not a CDC-ACM class device that creates a virtual COM port. My goal is to communicate with my USB device through bulk transfer, reading/writing to its endpoints. I know that implementing a driver for this purpose is usually necessary, but I have discovered that it is possible to use the generic WinUSB driver with the libusb library. Am I wrong?