Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option to force device connection #885

Open
patrickwasp opened this issue Mar 14, 2024 · 4 comments
Open

Option to force device connection #885

patrickwasp opened this issue Mar 14, 2024 · 4 comments

Comments

@patrickwasp
Copy link

patrickwasp commented Mar 14, 2024

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
@horchler
Copy link

horchler commented May 8, 2024

@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?

@charliebudd
Copy link

charliebudd commented May 13, 2024

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.

@charliebudd
Copy link

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);

@charliebudd
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants