aravis
aravis copied to clipboard
Option to force device connection
When starting an aravis program I sometimes get: Failed to bootstrap USB device '(null)-(null)-(null)-2978000AF0CC'
. I'm not sure exactly why this happens but unplugging the device and plugging it back it in fixes the issue, although it has to go through a (CID: DD4CCACF1905) device communication failure
error the first time it retries after being re-plugged in.
If possible a force
option when calling arv_camera_new()
to claim the device regardless of whatever else is using it would be helpful. If this is something deeper that cannot be done at the aravis level, are there any suggestions on a fix that doesn't involve physically unplugging?
lsusb -t
has the following output for the camera, without a Driver, when it doesn't work
|__ Port 1: Dev 2, If 0, Class=, Driver=, 5000M
|__ Port 1: Dev 2, If 1, Class=, Driver=, 5000M
When it works lsusb -t
shows
|__ Port 1: Dev 8, If 0, Class=, Driver=usbfs, 5000M
|__ Port 1: Dev 8, If 1, Class=, Driver=usbfs, 5000M
@patrickwasp have you tried arv_gv_device_take_control (ARV_GV_DEVICE (arv_camera_get_device (camera)), &error)
and arv_gv_device_leave_control (ARV_GV_DEVICE (arv_camera_get_device (camera)), &error)
for this?
It seems the suggested functions are for the GigEVision cameras denoted by gv
. An equivalent implementation for USB cameras could be provided, and then both implementations could be offered under a generic interface through the ArvDevice
or even the ArvCamera
class. The USB implementation could simply toggle the power of the USB device on/off, or use libusb to claim the interface, as in the snippet provided in #500.
I've been playing around with this a little using libusb. The code below finds no kernel driver active on my camera's interface and is able to successfully claim said interface. I then call libusb_reset_device
on the camera and close it. However, I still get the same Failed to bootstrap USB device
error.
static libusb_device* getDevice(libusb_context* ctx, int guid, libusb_device_descriptor* desc) {
libusb_device** device_list;
libusb_device* device;
ssize_t device_count = libusb_get_device_list(ctx, &device_list);
if (device_count < 0) {
std::cerr << "Failed to get device list" << std::endl;
return nullptr;
}
for (ssize_t i = 0; i < device_count; ++i) {
device = device_list[i];
if (libusb_get_device_descriptor(device, desc) != 0) {
std::cerr << "Failed to get device descriptor" << std::endl;
continue;
}
if (desc->idVendor == guid) {
libusb_free_device_list(device_list, 1);
return device;
}
}
libusb_free_device_list(device_list, 1);
return nullptr;
}
static void resetDevice(int guid) {
// Initialize libusb
libusb_context* ctx = nullptr;
if (libusb_init(&ctx) != 0) {
std::cerr << "Failed to initialize libusb" << std::endl;
return;
}
// Get matching device
libusb_device_descriptor desc;
libusb_device* dev = getDevice(ctx, guid, &desc);
if (dev == nullptr) {
std::cerr << "Failed to find device" << std::endl;
libusb_exit(ctx);
return;
}
libusb_device_handle* dev_handle = nullptr;
if (libusb_open(dev, &dev_handle) != 0) {
std::cerr << "Failed to open USB device" << std::endl;
libusb_exit(ctx);
return;
}
for (int i = 0; i < desc.bNumConfigurations; ++i) {
if(libusb_kernel_driver_active(dev_handle, i) == 1) {
std::cout << "Kernel drive active" << std::endl;
if(libusb_detach_kernel_driver(dev_handle, i) == 0) {
std::cout << "Kernel drive Detached" << std::endl;
}
else {
std::cout << "Couldn't detach kernel driver" << std::endl;
}
}
if (libusb_claim_interface(dev_handle, i) != 0) {
std::cerr << "Failed to claim interface " << i << std::endl;
continue;
}
libusb_release_interface(dev_handle, i);
std::cout << "Interface " << i << " claimed successfully" << std::endl;
}
libusb_reset_device(dev_handle);
libusb_close(dev_handle);
libusb_exit(ctx);
return;
}
std::string deviceGuidString = std::string(arv_get_device_physical_id(0)).substr(0, 4);
int deviceGuid = std::stoi(deviceGuidString, 0, 16);
resetDevice(deviceGuid);
After enabling debug...
[15:58:29.932] 🅸 device> SIRM_MAX_LEADER_SIZE = 0x00000040 [15:58:29.932] 🅸 device> SIRM_PAYLOAD_SIZE = 0x00100000 [15:58:29.932] 🅸 device> SIRM_PAYLOAD_COUNT = 0x00000005 [15:58:29.932] 🅸 device> SIRM_TRANSFER1_SIZE = 0x00000000 [15:58:29.932] 🅸 device> SIRM_TRANSFER2_SIZE = 0x00000000 [15:58:29.932] 🅸 device> SIRM_MAX_TRAILER_SIZE = 0x00000040 [15:58:29.932] 🆆 device> [UvDevice::_bootstrap] Error during memory read
I have narrowed down the problem to when _bootstrap
tries to read from manifest_table_address
...
https://github.com/AravisProject/aravis/blob/81ee947eba9d3805b11e12bad14558d9240378ed/src/arvuvdevice.c#L603C1-L610C3
This is interesting, I also bumped into issue with Basler (USB) camera sometimes. Not sure if this is because of usb port or other matters.
p/s: still a beginner, but I will try to setup for debugging as starting point