在 Linux 中,我有一个带有“寄存器”的 USB 集线器,如下图所示。该寄存器应该禁用集线器上某个端口的电源。
我尝试使用 LibUSB(我的代码如下所示)写入寄存器 0x0A,其中全为零以禁用所有端口。问题是,集线器由标准 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 驱动程序和写入失败?
#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”这个问题的简短答案是“你不能”。
为什么写入失败?这是另一回事。我建议调查一些事情:
- 检查从 libusb_bulk_transfer 返回的值,也许它会让您了解正在发生的事情。
- 听起来很愚蠢,但我总是先检查一下:进程权限。
另外,我可以建议另一种方法来解决这个问题,即 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/