【问题标题】:libusb can't claim devicelibusb 不能认领设备
【发布时间】:2017-07-05 07:13:48
【问题描述】:

我正在尝试使用 libusb-1.0 和 QtUsb 库来访问 USB 设备。在我进行一些更新之前,它是一个简单的大容量设备。 目前我使用

Linux 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

无论我以用户还是 root 身份运行都没有关系,因为设备将被 udev 设置为组用户和权限 666

[timestamp] [threadID] facility level [function call] <message>
--------------------------------------------------------------------------------
[ 0.012281] [00000fc6] libusb: error [op_get_configuration] device unconfigured
Type:1, cat:default, file:../src/qlibusb.cpp, line:114, f:virtual qint32 QUsbDevice::open(), msg:Cannot Claim Interface
Type:1, cat:default, file:../src/qlibusb.cpp, line:168, f:void QUsbDevice::printUsbError(int), msg:libusb Error: Entity not found
[ 0.951403] [00000fc6] libusb: warning [libusb_exit] application left some devices open

无论我以用户还是 root 身份运行都没有关系,因为设备将被 udev 设置为组用户和权限 666 欢迎任何提示

此致于尔根

代码

取自

QtUsb

用于 Qt 的跨平台 USB 库。 依赖 libusb-1.0。

特点

  • 批量传输
  • 设备插入/移除检测
  • 设备搜索

待办事项

  • 中断传输
  • 同步传输

用法

文档尚未完成,您可以同时查看示例。

文档

Doxygen 文档可以在这里找到:http://fpoussin.github.io/doxygen/qtusb/

下载

Ubuntu PPA:https://launchpad.net/~fpoussin/+archive/ubuntu/ppa Windows 库即将推出。

标题

    #ifndef USBEXAMPLE_H
    #define USBEXAMPLE_H

    #include <QObject>
    #include <QUsb>

    const quint8 USB_PIPE_IN = 0x81;   /* Bulk output endpoint for responses */
    const quint8 USB_PIPE_OUT = 0x01;      /* Bulk input endpoint for commands */
    const quint16 USB_TIMEOUT_MSEC = 300;

    const quint16 vendor_id = 0x04e3;
    const quint16 product_id= 0x0001;

    class UsbExample : public QObject
    {
        Q_OBJECT
    public:
        explicit UsbExample(QObject *parent = 0);
        ~UsbExample(void);
        void setupDevice(void);
        bool openDevice(void);
        bool closeDevice(void);
        void read(QByteArray *buf);
        void write(QByteArray *buf);

    signals:

    public slots:

    private:
        QUsbManager mUsbManager;
        QUsbDevice* mUsbDev;

        QtUsb::DeviceFilter mFilter;
        QtUsb::DeviceConfig mConfig;
    };

    #endif // USBEXAMPLE_H

cpp

    #include <iostream>
    #include "usbexample.h"

    using namespace std;

    #ifdef interface
    #undef interface
    #endif

    UsbExample::UsbExample(QObject *parent) : QObject(parent) {
      this->setupDevice();

      QByteArray send, recv;

      send.append(".[]=R00[]=R01[]=R02$");

      if (this->openDevice()) {
        cerr << "Device open!" << endl;
        this->write(&send);
        this->read(&recv);
      }
    }

    UsbExample::~UsbExample() { delete mUsbDev; }

    void UsbExample::setupDevice() {
      /* There are 2 ways of identifying devices depending on the platform.
       * You can use both methods, only one will be taken into account.
       */

      mUsbDev = new QUsbDevice();
      mUsbDev->setDebug(true);

    #if 1
      // Bus 003 Device 004: ID 04e3:0001 Zilog, Inc.
      mFilter.pid = 0x0001;
      mFilter.vid = 0x04E3;
    #else
      mFilter.vid = 0x0c4b;
      mFilter.pid = 0x0400;
    #endif

      //
      mConfig.alternate = 0;
      mConfig.config = 0;
      mConfig.interface = 0;
      mConfig.readEp = 0x81;
      mConfig.writeEp = 0x02;
    }

    bool UsbExample::openDevice() {
      cerr << "Opening" << endl;

      QtUsb::DeviceStatus ds;

      ds = mUsbManager.openDevice(mUsbDev, mFilter, mConfig);

      if (ds == QtUsb::deviceOK) {
        // Device is open
        return true;
      }
      return false;
    }

    bool UsbExample::closeDevice() {
      cerr << "Closing" << endl;
      mUsbManager.closeDevice(mUsbDev);
      return false;
    }

    void UsbExample::read(QByteArray *buf) { mUsbDev->read(buf, 1); }

    void UsbExample::write(QByteArray *buf) { mUsbDev->write(buf, buf->size()); }

    #include "usbexample.h"
    #include <QCoreApplication>
    #include <QTimer>
    #include <iostream>


    void customLogHandler(QtMsgType type, const QMessageLogContext& context,
                          const QString& msg)
    {
       // send the data to log file via the other thread
       // emit writeToFile(type, context, msg);

       // now output to debugger console
    #ifdef Q_OS_WIN
        OutputDebugString(text.toStdWString().c_str());
    #else
        std::cerr << "Type:" << type << ", cat:" << context.category << ", file:" << context.file
                      << ", line:" << context.line
                      << ", f:" << context.function << ", msg:" << msg.toStdString() << std::endl;
    #endif
    }


    int main(int argc, char *argv[]) {
        qInstallMessageHandler(&customLogHandler);
      QCoreApplication a(argc, argv);
      QTimer timer;

      QObject::connect(&timer, SIGNAL(timeout()), &a, SLOT(quit()));

      timer.setInterval(1000);
      timer.setSingleShot(true);
      timer.start();

      UsbExample example;

      return a.exec();
    }

【问题讨论】:

  • 你能分享你的代码吗?我可以看到错误消息“设备未配置”。你需要调试它。如果启用 libusb 调试可能会更好。
  • 要启用更多调试日志,请使用 libusb_set_debug()
  • 我做到了,调试已完全启用。
  • 可以分享代码吗?
  • 您的设备似乎没有使用 SET_CONFIGURATION 进行配置。这就是 get_configuration 失败的原因。可以先试试设置配置吗?

标签: linux usb libusb


【解决方案1】:

这是配置问题。在 USB 中,你必须服从层次结构

设备描述符-配置描述符-接口描述符-端点描述符

(http://www.beyondlogic.org/usbnutshell/usb1.shtml)

如果配置级别出现错误,所有其他级别也会失败

这个代码很可能是错误:

  mConfig.alternate = 0;
  mConfig.config = 0;
  mConfig.interface = 0;
  mConfig.readEp = 0x81;
  mConfig.writeEp = 0x02;

问题是我不知道您设备的 USB 树的结构,所以您必须这样做。您可以通过lsusb -vusb-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;
}

来源:https://github.com/fpoussin/QtUsb/blob/master/src/qlibusb.cpp

这是“无法声明接口”错误消息的来源,因为设置准确配置存在问题。如前所述,尝试lsusb -vusb-devices 以获得正确的信息...

【讨论】:

  • [编辑:我认为答案是因为配置缓存是手动填充的,可能会跳过设置它的关键步骤。]
猜你喜欢
  • 2016-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多