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

时间:2017-02-24 16:11:58

标签: c++ linux libusb

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

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

错误讯息:

$ /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编写此Hub寄存器,动态禁用和启用端口,而无需取消注册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;

}

1 个答案:

答案 0 :(得分:1)

    // Registration Routes...
Route::get(LaravelLocalization::transRoute('routes.register_link')/{plan?}, ['as' => 'auth.register', 'uses' => 'Auth\AuthController@showRegistrationForm']);
Route::post(LaravelLocalization::transRoute('routes.register_link'), ['as' => 'auth.register', 'uses' => 'Auth\AuthController@postRegister']);

由于上面所写的内容,对“如何在不分离驱动程序的情况下执行I / O”这一问题的简短回答是“你不能”。

为什么写失败?这是另一回事。我建议你研究一些事情:

  1. 查看从libusb_bulk_transfer返回的值,也许它可以让您了解正在发生的事情。
  2. 听起来很愚蠢,但我总是先检查一下:进程权限。
  3. 另外,我可以提出另一种解决方案的方法,即sysfs。

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

    无论如何,访问字符设备文件和sysfs文件是在linux中访问驱动程序数据的一般方法。可能你甚至不需要使用libusb的API来编写那个单字节。