c++ - Linux C++ LibUSB 在 USB HUB 中写入寄存器

标签 c++ linux libusb

在 Linux 中,我有一个带有“寄存器”的 USB 集线器,如下图所示。该寄存器应该禁用集线器上某个端口的电源。

我尝试使用 LibUSB(我的代码如下所示)写入寄存器 0x​​0A,其中全为零以禁用所有端口。问题是,集线器由标准 Linux USB 集线器驱动程序控制,因此内核驱动程序是分离的。写入也失败。失败消息如下所示。

错误信息:

$ /mnt/apps/UsbPowerControl
5 Devices in list.
Vendor:Device = 1908:1320
Vendor:Device = 0403:6001
Vendor:Device = 289d:0010
Vendor:Device = 0424:2513
Vendor:Device = 1d6b:0002
Opening Device = 0424:2513
Device Opened
Kernel Driver Active
Kernel Driver Detached!
Claimed Interface
Data-><-
Writing Data...
libusb: error [submit_bulk_transfer] submiturb failed error -1 errno=2
Write Error
Released Interface

我如何使用 LibUSB 写入此集线器寄存器,动态禁用和启用端口,而不注销 Linux 驱动程序和写入失败?

enter image description here

#include <iostream>
#include <cassert>
#include <libusb-1.0/libusb.h>

using namespace std;

#define VENDOR_ID 0x0424
#define PRODUCT_ID 0x2513

int main() {

    libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices
    libusb_device_handle *dev_handle; //a device handle
    libusb_context *ctx = NULL; //a libusb session
    int r; //for return values
    ssize_t cnt; //holding number of devices in list
    r = libusb_init(&ctx); //initialize the library for the session we just declared
    if(r < 0) {
        cout<<"Init Error "<<r<<endl; //there was an error
        return 1;
    }
    libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in the documentation

    cnt = libusb_get_device_list(ctx, &devs); //get the list of devices
    if(cnt < 0) {
        cout<<"Get Device Error"<<endl; //there was an error
        return 1;
    }
    cout<<cnt<<" Devices in list."<<endl;

    for (size_t idx = 0; idx < cnt; ++idx) {
        libusb_device *device = devs[idx];
        libusb_device_descriptor desc = {0};

        int rc = libusb_get_device_descriptor(device, &desc);
        assert(rc == 0);

        printf("Vendor:Device = %04x:%04x\n", desc.idVendor, desc.idProduct);
    }

    printf("Opening Device = %04x:%04x\n", VENDOR_ID, PRODUCT_ID);

    dev_handle = libusb_open_device_with_vid_pid(ctx, VENDOR_ID, PRODUCT_ID); //these are vendorID and productID I found for my usb device
    if(dev_handle == NULL)
        cout<<"Cannot open device"<<endl;
    else
        cout<<"Device Opened"<<endl;
    libusb_free_device_list(devs, 1); //free the list, unref the devices in it

    unsigned char *data = new unsigned char[1]; //data to write
    data[0]=0b00000000;

    int actual; //used to find out how many bytes were written
    if(libusb_kernel_driver_active(dev_handle, 0) == 1) { //find out if kernel driver is attached
        cout<<"Kernel Driver Active"<<endl;
        if(libusb_detach_kernel_driver(dev_handle, 0) == 0) //detach it
            cout<<"Kernel Driver Detached!"<<endl;
    }
    r = libusb_claim_interface(dev_handle, 0); //claim interface 0 (the first) of device (mine had jsut 1)
    if(r < 0) {
        cout<<"Cannot Claim Interface"<<endl;
        return 1;
    }
    cout<<"Claimed Interface"<<endl;
    cout<<"Data->"<<data<<"<-"<<endl; //just to see the data we want to write : abcd
    cout<<"Writing Data..."<<endl;
    r = libusb_bulk_transfer(dev_handle, (0x0A | LIBUSB_ENDPOINT_OUT), data, 1, &actual, 0); //my device's out endpoint was 2, found with trial- the device had 2 endpoints: 2 and 129
    if(r == 0 && actual == 1) //we wrote the 1 bytes successfully
        cout<<"Writing Successful!"<<endl;
    else
        cout<<"Write Error"<<endl;

    r = libusb_release_interface(dev_handle, 0); //release the claimed interface
    if(r!=0) {
        cout<<"Cannot Release Interface"<<endl;
        return 1;
    }
    cout<<"Released Interface"<<endl;

    libusb_close(dev_handle); //close the device we opened
    libusb_exit(ctx); //needs to be called to end the

    delete[] data; //delete the allocated memory for data
    return 0;

}

最佳答案

int libusb_detach_kernel_driver (   libusb_device_handle *  dev,
int     interface_number 
)   
...
If successful, you will then be able to claim the interface and perform I/O.
...



int libusb_kernel_driver_active (   libusb_device_handle *  dev,
int     interface_number 
)   
...
If a kernel driver is active, you cannot claim the interface, and libusb will be unable to perform I/O.
...

根据上面的内容,“如何在不分离驱动程序的情况下执行 I/O”这个问题的简短答案是“你不能”。

为什么写入失败?这是另一回事。我建议调查一些事情:

  1. 检查从 libusb_bulk_transfer 返回的值,也许它会让您了解正在发生的事情。
  2. 听起来很愚蠢,但我总是先检查一下:进程权限。

另外,我可以建议另一种方法来解决这个问题,即 sysfs。

我假设 your device(am I right?)支持 EEPROM 和 SMBus 访问。这意味着这种支持应该体现在内核中 /sys/bus/i2c/devices/[some_device_id]/eeprom 附近的某个地方(可能是另一个设备号,另一个目录位置等,因为它是所有驱动程序相关的),但如果它可以像任何其他文件一样找到和读取(这很可能,除非设备有问题),那么它可能也应该能够写入它。如果读取有效,那么我建议将找到的文件的 hexdump -C 与数据表进行比较,如果数据看起来合法,请尝试直接写入您的寄存器(文件偏移量)。

无论如何,访问字符设备文件和sysfs文件是linux中访问驱动程序数据的通用方式。可能您甚至不需要使用 libusb 的 API 来写入该单个字节。

关于c++ - Linux C++ LibUSB 在 USB HUB 中写入寄存器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42443292/

相关文章:

c++ - “warning: not all control paths return a value”是什么意思? (C++)

python - 设备在 PyUSB 上不可用

python - 在 Python 中查询连接的 USB 设备信息的简单方法?

linux - 声明日期变量的 Shell 脚本

linux - bash shell : How can I know if TeamViewer has disconnected?

windows - libusb-win32 - 无法从键盘读取

c++ - 什么可能导致在 C++ 中指针的另一端丢失对象?

c++ - 运行时检查失败 #2 - 变量 'sample' 周围的堆栈已损坏

c++ - GDB 在使用核心转储时给出无用的回溯

mysql - 针对 100 多个 wp 数据库和低 RAM 使用率优化 my.cnf