我正在尝试使用 libusb-1.0 和 QtUsb 库进行 USB 设备访问。它是一个简单的批量设备,在我进行一些更新之前就可以工作。\n目前我使用
\n\nLinux nadhh.fritz.box 4.11.8-200.fc25.x86_64 #1 SMP Thu Jun 29 16:13:56 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux\nRun Code Online (Sandbox Code Playgroud)\n\n我以用户或 root 身份运行并不重要,因为设备将被 udev 设置为组用户和权限 666
\n\n[timestamp] [threadID] facility level [function call] <message>\n--------------------------------------------------------------------------------\n[ 0.012281] [00000fc6] libusb: error [op_get_configuration] device unconfigured\nType:1, cat:default, file:../src/qlibusb.cpp, line:114, f:virtual qint32 QUsbDevice::open(), msg:Cannot Claim Interface\nType:1, cat:default, file:../src/qlibusb.cpp, line:168, f:void QUsbDevice::printUsbError(int), msg:libusb Error: Entity not found\n[ 0.951403] [00000fc6] libusb: warning [libusb_exit] application left some devices open\nRun Code Online (Sandbox Code Playgroud)\n\n我是否以用户或 root 身份运行并不重要,因为设备将被 udev 设置为组用户和权限 666\n欢迎任何提示
\n\n此致 J\xc3\xbcrgen
\n\n代码
\n\n取自
\n\n\n
\n\n用于 Qt 的跨平台 USB 库。\n依赖于 libusb-1.0。
\n\n特征
\n\n去做
\n\n用法
\n\n文档尚未完成,您可以同时查看示例。
\n\n文档
\n\nDoxygen 文档可以在这里找到: http: //fpoussin.github.io/doxygen/qtusb/
\n\n下载
\n\nUbuntu PPA:https://launchpad.net/~fpoussin/+archive/ubuntu/ppa \nWindows 库即将推出。
\n\n标头
\n\n #ifndef USBEXAMPLE_H\n #define USBEXAMPLE_H\n\n #include <QObject>\n #include <QUsb>\n\n const quint8 USB_PIPE_IN = 0x81; /* Bulk output endpoint for responses */\n const quint8 USB_PIPE_OUT = 0x01; /* Bulk input endpoint for commands */\n const quint16 USB_TIMEOUT_MSEC = 300;\n\n const quint16 vendor_id = 0x04e3;\n const quint16 product_id= 0x0001;\n\n class UsbExample : public QObject\n {\n Q_OBJECT\n public:\n explicit UsbExample(QObject *parent = 0);\n ~UsbExample(void);\n void setupDevice(void);\n bool openDevice(void);\n bool closeDevice(void);\n void read(QByteArray *buf);\n void write(QByteArray *buf);\n\n signals:\n\n public slots:\n\n private:\n QUsbManager mUsbManager;\n QUsbDevice* mUsbDev;\n\n QtUsb::DeviceFilter mFilter;\n QtUsb::DeviceConfig mConfig;\n };\n\n #endif // USBEXAMPLE_H\nRun Code Online (Sandbox Code Playgroud)\n\n程序文件
\n\n #include <iostream>\n #include "usbexample.h"\n\n using namespace std;\n\n #ifdef interface\n #undef interface\n #endif\n\n UsbExample::UsbExample(QObject *parent) : QObject(parent) {\n this->setupDevice();\n\n QByteArray send, recv;\n\n send.append(".[]=R00[]=R01[]=R02$");\n\n if (this->openDevice()) {\n cerr << "Device open!" << endl;\n this->write(&send);\n this->read(&recv);\n }\n }\n\n UsbExample::~UsbExample() { delete mUsbDev; }\n\n void UsbExample::setupDevice() {\n /* There are 2 ways of identifying devices depending on the platform.\n * You can use both methods, only one will be taken into account.\n */\n\n mUsbDev = new QUsbDevice();\n mUsbDev->setDebug(true);\n\n #if 1\n // Bus 003 Device 004: ID 04e3:0001 Zilog, Inc.\n mFilter.pid = 0x0001;\n mFilter.vid = 0x04E3;\n #else\n mFilter.vid = 0x0c4b;\n mFilter.pid = 0x0400;\n #endif\n\n //\n mConfig.alternate = 0;\n mConfig.config = 0;\n mConfig.interface = 0;\n mConfig.readEp = 0x81;\n mConfig.writeEp = 0x02;\n }\n\n bool UsbExample::openDevice() {\n cerr << "Opening" << endl;\n\n QtUsb::DeviceStatus ds;\n\n ds = mUsbManager.openDevice(mUsbDev, mFilter, mConfig);\n\n if (ds == QtUsb::deviceOK) {\n // Device is open\n return true;\n }\n return false;\n }\n\n bool UsbExample::closeDevice() {\n cerr << "Closing" << endl;\n mUsbManager.closeDevice(mUsbDev);\n return false;\n }\n\n void UsbExample::read(QByteArray *buf) { mUsbDev->read(buf, 1); }\n\n void UsbExample::write(QByteArray *buf) { mUsbDev->write(buf, buf->size()); }\n\n #include "usbexample.h"\n #include <QCoreApplication>\n #include <QTimer>\n #include <iostream>\n\n\n void customLogHandler(QtMsgType type, const QMessageLogContext& context,\n const QString& msg)\n {\n // send the data to log file via the other thread\n // emit writeToFile(type, context, msg);\n\n // now output to debugger console\n #ifdef Q_OS_WIN\n OutputDebugString(text.toStdWString().c_str());\n #else\n std::cerr << "Type:" << type << ", cat:" << context.category << ", file:" << context.file\n << ", line:" << context.line\n << ", f:" << context.function << ", msg:" << msg.toStdString() << std::endl;\n #endif\n }\n\n\n int main(int argc, char *argv[]) {\n qInstallMessageHandler(&customLogHandler);\n QCoreApplication a(argc, argv);\n QTimer timer;\n\n QObject::connect(&timer, SIGNAL(timeout()), &a, SLOT(quit()));\n\n timer.setInterval(1000);\n timer.setSingleShot(true);\n timer.start();\n\n UsbExample example;\n\n return a.exec();\n }\nRun Code Online (Sandbox Code Playgroud)\n
这是配置问题。在USB中你必须遵守层次结构
设备描述符 - 配置描述符 - 接口描述符 - 端点描述符
(http://www.beyondlogic.org/usbnutshell/usb1.shtml)
如果配置级别出现错误,所有其他级别也会失败
错误很可能出现在这段代码中:
mConfig.alternate = 0;
mConfig.config = 0;
mConfig.interface = 0;
mConfig.readEp = 0x81;
mConfig.writeEp = 0x02;
Run Code Online (Sandbox Code Playgroud)
问题是我不知道您设备的 USB 树的结构,所以您必须这样做。lsusb -v您可以通过或获取结构usb-devices,并在设备中搜索结构顺序“设备-配置-接口-端点”
如果您有信息,则必须修改上述代码(即更改接口索引,备用设置,...)
源代码的关键部分是
int conf;
libusb_get_configuration(mDevHandle, &conf);
if (conf != mConfig.config) {
if (mDebug) qDebug("Configuration needs to be changed");
rc = libusb_set_configuration(mDevHandle, mConfig.config);
if (rc != 0) {
qWarning("Cannot Set Configuration");
this->printUsbError(rc);
return -3;
}
}
rc = libusb_claim_interface(mDevHandle, mConfig.interface);
if (rc != 0) {
qWarning("Cannot Claim Interface");
this->printUsbError(rc);
return -4;
}
Run Code Online (Sandbox Code Playgroud)
来源:https ://github.com/fpoussin/QtUsb/blob/master/src/qlibusb.cpp
这就是“无法声明接口”错误消息的来源,因为设置准确的配置存在问题。正如所说,尝试lsusb -v或usb-devices获取正确的信息......